From: Markus Fritsche Date: 2026-05-05 Subject: [PATCH] sandbox/linux: allow V4L2 stateless request-API decoders in RDD Firefox's RDD process sandbox blocks hardware video decode for V4L2 stateless decoders (hantro G1/G2 on RK35xx, cedrus on Allwinner, etc.). Three distinct gates close the door: 1. Broker policy: AddV4l2Dependencies() filters /dev/video* by VIDEO_M2M / VIDEO_M2M_MPLANE capability. Stateless decoders advertise CAPTURE_MPLANE + OUTPUT_MPLANE + STREAMING but typically not M2M, so /dev/video1 (the hantro device) is silently dropped. 2. Broker policy: GetRDDPolicy() never references /dev/media*. The V4L2 request API (MEDIA_REQUEST_IOC_QUEUE et al), required for stateless decode, lives on /dev/media* nodes that the broker won't open from RDD. 3. Seccomp policy: RDDSandboxPolicy::EvaluateSyscall's ioctl handler allowlists ioctl magic byte 'V' (V4L2) but not '|' (linux/media.h). Even after broker permits the open, the kernel ioctl path is filtered, returning ENOSYS to userspace and causing libva to abandon decode. (Empirically confirmed iter3 Phase 7: "Unable to allocate media request: Function not implemented".) Tested: libva-v4l2-request-fourier on PineTab2 (RK3568, hantro G1) playing bbb_1080p30 H.264 in Firefox 150 without MOZ_DISABLE_RDD_SANDBOX=1. --- --- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp +++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp @@ -901,8 +901,16 @@ } if ((cap.device_caps & V4L2_CAP_VIDEO_M2M) || - (cap.device_caps & V4L2_CAP_VIDEO_M2M_MPLANE)) { - // This is an M2M device (i.e. not a webcam), so allow access + (cap.device_caps & V4L2_CAP_VIDEO_M2M_MPLANE) || + // V4L2 stateless decoders (hantro G1/G2 on Rockchip, cedrus on + // Allwinner, etc.) report CAPTURE_MPLANE + OUTPUT_MPLANE + + // STREAMING but do not set the M2M caps. They use the request API + // via /dev/media* (see AddV4l2RequestApiDependencies below). + ((cap.device_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) && + (cap.device_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) && + (cap.device_caps & V4L2_CAP_STREAMING))) { + // This is an M2M or stateless decode device (i.e. not a webcam), + // so allow access policy->AddPath(rdwr, path.get()); } @@ -913,6 +921,32 @@ // FFmpeg V4L2 needs to list /dev to find V4L2 devices. policy->AddPath(rdonly, "/dev"); } + +// V4L2 stateless decoders submit per-frame decode requests via the +// media-controller framework on /dev/media* nodes (ioctls in the +// MEDIA_REQUEST_IOC_* family, magic byte '|', defined in ). +// These are required alongside /dev/video* for any request-API decoder. +// We allow rdwr access to all /dev/media* nodes; the kernel's +// media-controller layer enforces device-level access control. +// This mirrors the model AddV4l2Dependencies uses for /dev/video*. +static void AddV4l2RequestApiDependencies(SandboxBroker::Policy* policy) { + DIR* dir = opendir("/dev"); + if (!dir) { + SANDBOX_LOG("Couldn't list /dev for media-controller nodes"); + return; + } + + struct dirent* dir_entry; + while ((dir_entry = readdir(dir))) { + if (strncmp(dir_entry->d_name, "media", 5)) { + continue; + } + nsCString path = "/dev/"_ns; + path += nsDependentCString(dir_entry->d_name); + policy->AddPath(rdwr, path.get()); + } + closedir(dir); +} #endif // MOZ_ENABLE_V4L2 /* static */ UniquePtr @@ -979,6 +1013,7 @@ #ifdef MOZ_ENABLE_V4L2 AddV4l2Dependencies(policy.get()); + AddV4l2RequestApiDependencies(policy.get()); #endif // MOZ_ENABLE_V4L2 // Bug 1903688: NVIDIA Tegra hardware decoding from Linux4Tegra --- a/security/sandbox/linux/SandboxFilter.cpp +++ b/security/sandbox/linux/SandboxFilter.cpp @@ -2067,6 +2067,11 @@ // Type 'V' for V4L2, used for hw accelerated decode static constexpr unsigned long kVideoType = static_cast('V') << _IOC_TYPESHIFT; + // Type '|' for the V4L2 request API on /dev/media* nodes + // (MEDIA_REQUEST_IOC_QUEUE et al, defined in ). + // Required by V4L2 stateless decoders such as hantro/cedrus/sun*. + static constexpr unsigned long kMediaType = + static_cast('|') << _IOC_TYPESHIFT; #endif // nvidia non-tegra uses some ioctls from this range (but not actual // fbdev ioctls; nvidia uses values >= 200 for the NR field @@ -2088,6 +2093,7 @@ .ElseIf(shifted_type == kDmaBufType, Allow()) #ifdef MOZ_ENABLE_V4L2 .ElseIf(shifted_type == kVideoType, Allow()) + .ElseIf(shifted_type == kMediaType, Allow()) #endif // NVIDIA decoder from Linux4Tegra, this is specific to Tegra ARM64 SoC #if defined(__aarch64__)