30fadc33910545934d39d29ff1d9d73c15553aba Fix null delegate dereference in MediaDevicesPermissionChecker
The bug at a glance
The fix adds a null check for RenderFrameHostImpl::delegate() before a virtual call in the browser process; a null-pointer dereference here is a non-exploitable crash (browser-process DoS), not memory corruption, and it requires hitting a narrow frame-detachment window.
A page can request media-device permission checks (e.g., via device enumeration) and race them against frame teardown to crash the browser process; defenders care because browser-side null derefs on detaching RenderFrameHosts are a recurring, web-reachable crash pattern.
Root cause
DoCheckPermissionsOnUIThread looks up the RenderFrameHost and then calls frame_host->delegate()->CheckMediaAccessPermission(…). When the RenderFrameHost is mid-detachment or destruction, delegate() can return nullptr, and the subsequent call dereferences null. The patch returns an all-false MediaDevicesManager::BoolDeviceTypes() when delegate is null, denying device permissions instead of crashing.
Key code
Null delegate guard before CheckMediaAccessPermission
RenderFrameHostDelegate* delegate = frame_host->delegate();
+ if (!delegate) {
+ return MediaDevicesManager::BoolDeviceTypes();
+ }
Patch walkthrough
content/browser/media/media_devices_permission_checker.cc— Adds a null check on frame_host->delegate() in the UI-thread permission check, failing closed (all device types denied) instead of dereferencing a null delegate during frame detachment/destruction.
Background
MediaDevicesPermissionChecker — Browser-process helper that determines whether a frame may see/access microphone, camera and speaker devices, used by media device enumeration and related APIs.
RenderFrameHostImpl::delegate() — Returns the owning WebContents-side delegate, which may be null while the frame is being detached or destroyed.
Vulnerability window
- Reachability — Likely ordinary web content in a stock build via media-devices APIs that trigger permission checks (inferred), but only during a frame detachment/destruction race window.
- Trigger — A permission check is posted to the UI thread for a frame that is concurrently being removed, so frame_host is still found but delegate() returns nullptr (inferred timing).
- Primitive — Null-pointer virtual call in the browser process, producing a crash (DoS); no controlled memory access.
- Escalation — None evident; null-page dereferences are not exploitable on modern platforms (inferred).
Proof of concept
Conceptually, a page repeatedly triggers media-device permission checks from a subframe while removing or navigating that subframe, aiming for the check to run on the UI thread after the frame has begun detaching so delegate() is null.
Exploitation
- Race setup — Interleave media device permission checks with frame teardown (inferred).
- Impact — Browser-process crash (denial of service) only; fix fails closed so no permission bypass is introduced.
Detection & hunting
For defenders and detection engineers:
- weggli ‘{ $T $d = $f->delegate(); not: if (!$d) {} $d->$m(_); }’ content/browser* — Find RenderFrameHost delegate() results used without null checks in browser-side handlers that can run during frame teardown.
- Crash stacks in DoCheckPermissionsOnUIThread / CheckMediaAccessPermission — Monitor crash reports for null derefs in media permission checking on the UI thread.
Audit directions
- content/browser/media/ (media_devices_, media_stream_) — Audit other UI-thread hops that fetch a RenderFrameHost by ID and then use delegate() or GetWebContents() without null checks.
- content/browser/renderer_host/ callers of RenderFrameHostImpl::delegate() — Check asynchronous callbacks that may run after frame detachment begins for unchecked delegate usage.