Firefox · Widget
CVE-2026-92033
Logic Error in Widget
Overview
Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ProcessManagerProxymobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java |
modified | |
ifmobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java |
modified |
Files Changed
ipc/glue/GeckoChildProcessHost.cppmobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IProcessManager.aidlmobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.javamobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.javawidget/android/GeckoEditableSupport.cppwidget/android/GeckoEditableSupport.hwidget/android/GeckoProcessManager.cppwidget/android/GeckoProcessManager.h
Patch
diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp
index 47e3c55ccad..e2b4d823617 100644
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -323,7 +323,8 @@ class AndroidProcessLauncher : public PosixProcessLauncher {
protected:
virtual RefPtr<ProcessLaunchPromise> DoLaunch() override;
RefPtr<ProcessHandlePromise> LaunchAndroidService(
- const GeckoProcessType aType, const geckoargs::ChildProcessArgs& args);
+ const GeckoProcessType aType, const GeckoChildID aChildID,
+ const geckoargs::ChildProcessArgs& args);
};
typedef AndroidProcessLauncher ProcessLauncher;
// NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
@@ -1346,7 +1347,7 @@ Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() {
#if defined(MOZ_WIDGET_ANDROID)
RefPtr<ProcessLaunchPromise> AndroidProcessLauncher::DoLaunch() {
- return LaunchAndroidService(mProcessType, mChildArgs)
+ return LaunchAndroidService(mProcessType, mChildID, mChildArgs)
->Then(
mLaunchThread, __func__,
[self = RefPtr{this}](ProcessHandle aHandle) {
@@ -1824,7 +1825,8 @@ RefPtr<ProcessHandlePromise> GeckoChildProcessHost::WhenProcessHandleReady() {
#ifdef MOZ_WIDGET_ANDROID
RefPtr<ProcessHandlePromise> AndroidProcessLauncher::LaunchAndroidService(
- const GeckoProcessType aType, const geckoargs::ChildProcessArgs& args) {
+ const GeckoProcessType aType, const GeckoChildID aChildId,
+ const geckoargs::ChildProcessArgs& args) {
JNIEnv* const env = mozilla::jni::GetEnvForThread();
MOZ_ASSERT(env);
@@ -1842,7 +1844,8 @@ RefPtr<ProcessHandlePromise> AndroidProcessLauncher::LaunchAndroidService(
jni::IntArray::LocalRef jfds = jni::IntArray::New(fds.data(), fds.size());
auto type = java::GeckoProcessType::FromInt(aType);
- auto genericResult = java::GeckoProcessManager::Start(type, jargs, jfds);
+ auto genericResult =
+ java::GeckoProcessManager::Start(type, aChildId, jargs, jfds);
auto typedResult = java::GeckoResult::LocalRef(std::move(genericResult));
return ProcessHandlePromise::FromGeckoResult(typedResult);
}
diff --git a/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IProcessManager.aidl b/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IProcessManager.aidl
index 224df64fc82..c4d1c0481e8 100644
--- a/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IProcessManager.aidl
+++ b/mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/process/IProcessManager.aidl
@@ -10,7 +10,7 @@ import org.mozilla.gecko.gfx.ISurfaceAllocator;
import android.os.IBinder;
interface IProcessManager {
- void getEditableParent(in IGeckoEditableChild child, long contentId, long tabId);
+ void getEditableParent(in IGeckoEditableChild child, long tabId);
// Returns the interface that child processes should use to allocate Surfaces.
ISurfaceAllocator getSurfaceAllocator(in IBinder client);
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
index 2d02a89e004..e9ce617350a 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoProcessManager.java
@@ -34,11 +34,14 @@ import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.gecko.util.XPCOMEventTarget;
import org.mozilla.geckoview.GeckoResult;
-public final class GeckoProcessManager extends IProcessManager.Stub {
+public final class GeckoProcessManager {
private static final String LOGTAG = "GeckoProcessManager";
private static final GeckoProcessManager INSTANCE = new GeckoProcessManager();
private static final int INVALID_PID = 0;
+ /** For Preload process that doesn't start Gecko */
+ private static final int PRELOAD_CHILD_ID = -1;
+
// This id univocally identifies the current process manager instance
private final String mInstanceId;
@@ -61,12 +64,27 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
@WrapForJNI(stubName = "GetEditableParent", dispatchTo = "gecko")
private static native void nativeGetEditableParent(
- IGeckoEditableChild child, long contentId, long tabId);
+ IGeckoEditableChild child, int contentId, long tabId);
+
+ /** The IProcessManager implementation handed to an individual child process. */
+ private static final class ProcessManagerProxy extends IProcessManager.Stub {
+ private final ChildConnection mConnection;
+
+ ProcessManagerProxy(@NonNull final ChildConnection connection) {
+ mConnection = connection;
+ }
+
+ @Override // IProcessManager
+ public void getEditableParent(final IGeckoEditableChild child, final long tabId) {
+ nativeGetEditableParent(child, mConnection.getChildId(), tabId);
+ }
- @Override // IProcessManager
- public void getEditableParent(
- final IGeckoEditableChild child, final long contentId, final long tabId) {
- nativeGetEditableParent(child, contentId, tabId);
+ @Override // IProcessManager
+ public ISurfaceAllocator getSurfaceAllocator(final IBinder client) {
+ // TODO(m_kato): This is a GPU process connection, we can use
+ // GpuProcessConnection.getSurfaceAllocator() directly.
+ return INSTANCE.getSurfaceAllocator(client);
+ }
}
/**
@@ -74,7 +92,6 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
* The service bound to the returned interface may live in either the GPU process or parent
* process.
*/
- @Override // IProcessManager
public ISurfaceAllocator getSurfaceAllocator(final IBinder client) {
final boolean gpuEnabled = GeckoAppShell.isGpuProcessEnabled();
@@ -187,13 +204,16 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private IChildProcess mChild;
private GeckoResult<IChildProcess> mPendingBind;
private int mPid;
+ private int mChildId;
protected ChildConnection(
@NonNull final ServiceAllocator allocator,
@NonNull final GeckoProcessType type,
- @NonNull final PriorityLevel initialPriority) {
+ @NonNull final PriorityLevel initialPriority,
+ final int childId) {
super(allocator, type, initialPriority);
mPid = INVALID_PID;
+ mChildId = childId;
}
public int getPid() throws AssertionError, IncompleteChildConnectionException {
@@ -206,6 +226,24 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
return mPid;
}
+ public int getChildId() {
+ return mChildId;
+ }
+
+ protected void setChildId(final int childId) {
+ XPCOMEventTarget.assertOnLauncherThread();
+ mChildId = childId;
+ }
+
+ protected ProcessManagerProxy createProcessManagerProxy() {
+ XPCOMEventTarget.assertOnLauncherThread();
+ if (mChildId == PRELOAD_CHILD_ID) {
+ throw new IllegalStateException("Starting a child process with preload child ID");
+ }
+
+ return new ProcessManagerProxy(this);
+ }
+
protected IChildProcess getChild() {
return mChild;
}
@@ -320,8 +358,10 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private static class NonContentConnection extends ChildConnection {
public NonContentConnection(
- @NonNull final ServiceAllocator allocator, @NonNull final GeckoProcessType type) {
- super(allocator, type, PriorityLevel.FOREGROUND);
+ @NonNull final ServiceAllocator allocator,
+ @NonNull final GeckoProcessType type,
+ final int childId) {
+ super(allocator, type, PriorityLevel.FOREGROUND, childId);
if (GeckoProcessManager.isContent(type)) {
throw new AssertionError("Attempt to create a NonContentConnection as CONTENT");
}
@@ -345,11 +385,13 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
// Static counter used to initialize each instance's mUniqueGpuProcessId
private static int sUniqueGpuProcessIdCounter = 0;
- public GpuProcessConnection(@NonNull final ServiceAllocator allocator) {
- super(allocator, GeckoProcessType.GPU);
+ public GpuProcessConnection(@NonNull final ServiceAllocator allocator, final int childId) {
+ super(allocator, GeckoProcessType.GPU, childId);
// Initialize the unique ID ensuring we skip 0 (as that is reserved for parent process
// allocators).
+ //
+ // TODO(m_kato): Use ChildConnection.childId instead.
if (sUniqueGpuProcessIdCounter == 0) {
sUniqueGpuProcessIdCounter++;
}
@@ -382,8 +424,8 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private boolean mIsForeground = true;
private boolean mIsNetworkUp = true;
- public SocketProcessConnection(@NonNull final ServiceAllocator allocator) {
- super(allocator, GeckoProcessType.SOCKET);
+ public SocketProcessConnection(@NonNull final ServiceAllocator allocator, final int childId) {
+ super(allocator, GeckoProcessType.SOCKET, childId);
GeckoProcessManager.INSTANCE.mConnections.enableNetworkNotifications();
}
@@ -429,8 +471,10 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private static final class ContentConnection extends ChildConnection {
public ContentConnection(
- @NonNull final ServiceAllocator allocator, @NonNull final PriorityLevel initialPriority) {
- super(allocator, GeckoProcessType.determineContentProcessType(), initialPriority);
+ @NonNull final ServiceAllocator allocator,
+ @NonNull final PriorityLevel initialPriority,
+ final int childId) {
+ super(allocator, GeckoProcessType.determineContentProcessType(), initialPriority, childId);
}
@Override
@@ -609,8 +653,10 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
}
/** Unconditionally create a new content connection for the specified priority. */
- private ContentConnection getNewContentConnection(@NonNull final PriorityLevel newPriority) {
- final ContentConnection result = new ContentConnection(mServiceAllocator, newPriority);
+ private ContentConnection getNewContentConnection(
+ @NonNull final PriorityLevel newPriority, final int childId) {
+ final ContentConnection result =
+ new ContentConnection(mServiceAllocator, newPriority, childId);
mContentConnections.add(result);
return result;
@@ -633,21 +679,25 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
* Retrieve a ChildConnection for a content process for the purposes of starting. If there are
* any preloaded content processes already running, we will use one of those. Otherwise we will
* allocate a new ChildConnection.
+ *
+ * @param childId The new child ID to assign to the connection.
*/
- private ChildConnection getContentConnectionForStart() {
+ private ChildConnection getContentConnectionForStart(final int childId) {
XPCOMEventTarget.assertOnLauncherThread();
if (mNonStartedContentConnections.isEmpty()) {
- return getNewContentConnection(PriorityLevel.FOREGROUND);
+ return getNewContentConnection(PriorityLevel.FOREGROUND, childId);
}
final ChildConnection conn = mNonStartedContentConnections.removeFirst();
conn.setPriorityLevel(PriorityLevel.FOREGROUND);
+ conn.setChildId(childId);
return conn;
}
/** Retrieve or create a new child process for the specified non-content process. */
- private ChildConnection getNonContentConnection(@NonNull final GeckoProcessType type) {
+ private ChildConnection getNonContentConnection(
+ @NonNull final GeckoProcessType type, final int childId) {
XPCOMEventTarget.assertOnLauncherThread();
if (isContent(type)) {
throw new IllegalArgumentException("Content processes not supported by this method");
@@ -656,37 +706,44 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
NonContentConnection connection = mNonContentConnections.get(type);
if (connection == null) {
if (type == GeckoProcessType.SOCKET) {
- connection = new SocketProcessConnection(mServiceAllocator);
+ connection = new SocketProcessConnection(mServiceAllocator, childId);
} else if (type == GeckoProcessType.GPU) {
- connection = new GpuProcessConnection(mServiceAllocator);
+ connection = new GpuProcessConnection(mServiceAllocator, childId);
} else {
- connection = new NonContentConnection(mServiceAllocator, type);
+ connection = new NonContentConnection(mServiceAllocator, type, childId);
}
mNonContentConnections.put(type, connection);
+ } else if (connection.getChildId() != childId) {
+ if (connection.getChildId() != PRELOAD_CHILD_ID) {
+ throw new IllegalArgumentException("Connection already has childId set?");
+ }
+ connection.setChildId(childId);
}
return connection;
}
/** Retrieve a ChildConnection for the purposes of starting a new child process. */
- public ChildConnection getConnectionForStart(@NonNull final GeckoProcessType type) {
+ public ChildConnection getConnectionForStart(
+ @NonNull final GeckoProcessType type, final int childId) {
if (isContent(type)) {
- return getContentConnectionForStart();
+ return getContentConnectionForStart(childId);
}
- return getNonContentConnection(type);
+ return getNonContentConnection(type, childId);
}
/** Retrieve a ChildConnection for the purposes of preloading a new child process. */
public ChildConnection getConnectionForPreload(@NonNull final GeckoProcessType type) {
if (isContent(type)) {
- final ContentConnection conn = getNewContentConnection(PriorityLevel.BACKGROUND);
+ final ContentConnection conn =
+ getNewContentConnection(PriorityLevel.BACKGROUND, PRELOAD_CHILD_ID);
mNonStartedContentConnections.addLast(conn);
return conn;
}
- return getNonContentConnection(type);
+ return getNonContentConnection(type, PRELOAD_CHILD_ID);
}
}
@@ -790,11 +847,12 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
@WrapForJNI
private static GeckoResult<Integer> start(
- final GeckoProcessType type, final String[] args, final int[] fds) {
+ final GeckoProcessType type, final int childId, final String[] args, final int[] fds) {
final GeckoResult<Integer> result = new GeckoResult<>();
final StartInfo info =
new StartInfo(
type,
+ childId,
GeckoThread.InitInfo.builder()
.args(args)
.userSerialNumber(System.getenv("MOZ_ANDROID_USER_SERIAL_NUMBER"))
@@ -830,13 +888,16 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private static class StartInfo {
final GeckoProcessType type;
+ final int childId;
final String crashHandler;
final GeckoThread.InitInfo init;
final ParcelFileDescriptor[] pfds;
- private StartInfo(final GeckoProcessType type, final GeckoThread.InitInfo initInfo) {
+ private StartInfo(
+ final GeckoProcessType type, final int childId, final GeckoThread.InitInfo initInfo) {
this.type = type;
+ this.childId = childId;
this.init = initInfo;
crashHandler =
GeckoAppShell.getCrashHandlerService() != null
@@ -944,14 +1005,14 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
private GeckoResult<Integer> startInternal(final StartInfo info) {
XPCOMEventTarget.assertOnLauncherThread();
- final ChildConnection connection = mConnections.getConnectionForStart(info.type);
+ final ChildConnection connection = mConnections.getConnectionForStart(info.type, info.childId);
return connection
.bind()
.map(
child -> {
final int result =
child.start(
- this,
+ connection.createProcessManagerProxy(),
mInstanceId,
info.init.args,
info.init.extras,
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
index f50ea854d1d..d0da701402c 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/process/GeckoServiceChildProcess.java
@@ -42,10 +42,9 @@ public class GeckoServiceChildProcess extends Service {
private static ProcessState sState = ProcessState.NEW;
@WrapForJNI(calledFrom = "gecko")
- private static void getEditableParent(
- final IGeckoEditableChild child, final long contentId, final long tabId) {
+ private static void getEditableParent(final IGeckoEditableChild child, final long tabId) {
try {
- sProcessManager.getEditableParent(child, contentId, tabId);
+ sProcessManager.getEditableParent(child, tabId);
} catch (final RemoteException e) {
Log.e(LOGTAG, "Cannot get editable", e);
}
diff --git a/widget/android/GeckoEditableSupport.cpp b/widget/android/GeckoEditableSupport.cpp
index c02a7896bd2..8fa5e6439a6 100644
--- a/widget/android/GeckoEditableSupport.cpp
+++ b/widget/android/GeckoEditableSupport.cpp
@@ -1336,14 +1336,11 @@ nsresult GeckoEditableSupport::NotifyIME(
}
if (!mEditable->HasEditableParent()) {
- const dom::ContentChild* const contentChild =
- dom::ContentChild::GetSingleton();
if (dom::BrowserChild* browserChild =
widget->GetOwningBrowserChild()) {
- const uint64_t contentId = contentChild->GetID();
const uint64_t tabId = browserChild->GetTabId();
- EnsureEditableParent(contentId, tabId);
+ EnsureEditableParent(tabId);
}
}
@@ -1605,16 +1602,14 @@ void GeckoEditableSupport::TransferParent(jni::Object::Param aEditableParent) {
}
}
-void GeckoEditableSupport::EnsureEditableParent(uint64_t aContentId,
- uint64_t aTabId) {
... (file diff truncated)
Loading diff…
References
On This Page