Display-only NativeImages recorded across processes
Component: WebKit Site Isolation | d1179a9
Source/WebKit/GPUProcess/GPUProcess.cpp
Source/WebKit/GPUProcess/graphics/RemoteSnapshotIdentifier.h
With site isolation, cross-origin iframes live in separate WebContent processes, so no single process can rasterize a page that contains them. Snapshots are recorded in the GPU process through RemoteSnapshot, and pixels move between processes as IOSurfaces, which are mach-port-backed shared surfaces.
Chrome::createDisplayOnlyImage() records a rendering in the GPU process that frames in other processes can draw into. It returns a promise for a NativeImage that the web process can display but not read. The GPU process draws into an IOSurface and gives it to the UI process, which keeps custody of it. The web process only receives a DisplayOnlyImageProxy, which releases the image when destroyed. Snapshot identifiers are now process-qualified.
Significance
Frames in different processes can be composited into one snapshot without any web process seeing the cross-origin pixels, which is groundwork for site-isolated view transitions.
Audit directions
This privileged cross-process surface has no caller yet, so it is unlikely to have been fuzzed. The rasterized handle is marked NeedsReview in opaque_ipc_types.tracking.in. Check whether the UI process validates that identifiers in completeDisplayOnlyImage/releaseDisplayOnlyImage belong to the sending process, via the pageHostedAs and ProcessQualified plumbing. Check lifetime when a web or GPU process dies mid-recording (removeSnapshotsForProcess, removeDisplayOnlyImagesForProcess, remotePageProcessDidTerminate). Check orderings such as double-complete, release-before-complete and duplicate identifiers. Check whether a compromised web process can make the UI process display or free another process's surface, and whether the IOSurface handle's size and format are checked against the requested size and scale.