Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2022-41218 — Vulnerability Details for CVE-2022-41218 | Kitploit
Tools/GitHubGitHub/tobey123/cve-2022-41218
Vulnerability AnalysisExploitationBinary Exploitation
GitHubtobey123/cve-2022-41218

CVE-2022-41218

Vulnerability Details for CVE-2022-41218

View Repository
4134 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Introduction

This vulnerability is a race condition vulnerability that occurs in drivers/media/dvb-core/dmxdev.c. Therefore, a race condition may occur in the usb device driver using this dmxdev.

This vulnerability could be used to trigger 3 UAFs.

Vulnerability

1. vmalloc UAF write

First, the order of the exploit is as follows(I debugged using drivers/media/usb/ttusb-dec/ttusb_dec.c):

                cpu0                                            cpu1                                    cpu 2
                                                        1. dvb_dvr_open()
2. ttusb_dec_disconnect()
   ttusb_dec_exit_dvb()
   dvb_dmxdev_release()
   wait_event(dmxdev->dvr_dvbdev->wait_queue, …)
                                                                                                3. dvb_demux_open()
                                                                                                   dvb_demux_ioctl()
                                                                                                   dvb_usercopy()
                                                                                                   copy_from_user()  <- userfaultfd stuck
                                                        4. dvb_dvr_release()
5. vfree(dmxdev->filter)
                                                                                                6. copy_from_user()    <- userfaultfd release
                                                                                                   dvb_demux_do_ioctl()
                                                                                                   struct dmxdev *dmxdev = dmxdevfilter->dev;  <- UAF!!

The detailed exploit flow is as follows:

  1. open() dvr0 among the device nodes. This calls dvb_dvr_open() to cause dvbdev->users++ to run. In this case, when ttusb_dec_disconnect() is executed by removing the usb device, the wait_event(dmxdev->dvr_dvbdev->wait_queue, …) condition is caught.

  2. Physically remove the USB device. In this case, while the ttusb_dec_disconnect() function is being executed, it waits at wait_event(dmxdev->dvr_dvbdev->wait_queue, …).

  3. open() the demux0 node so that the dvb_demux_open() function is called. This function also executes dvbdev->users++ similarly to the dvb_dvr_open() function in step 1. However, this improper reference counting occurs because the dvb_dmxdev_release() function that is currently waiting has already passed the check for dvbdev->users:

void dvb_dmxdev_release(struct dmxdev *dmxdev)
{
        dmxdev->exit = 1;
        if (dmxdev->dvbdev->users > 1) {    // This check is bypassed. improper reference counting.
                wait_event(dmxdev->dvbdev->wait_queue,
                                dmxdev->dvbdev->users == 1);
        }
        if (dmxdev->dvr_dvbdev->users > 1) {
                wait_event(dmxdev->dvr_dvbdev->wait_queue,    // Currently wait()ing here.
                                dmxdev->dvr_dvbdev->users == 1);
        }

        dvb_unregister_device(dmxdev->dvbdev);
        dvb_unregister_device(dmxdev->dvr_dvbdev);

        vfree(dmxdev->filter);
        dmxdev->filter = NULL;
        dmxdev->demux->close(dmxdev->demux);
}

It then calls ioctl() on demux0. When calling, the 3rd argument submits the user-space address set by userfaultfd(or FUSE fs). Now while ioctl is running it will hang at copy_from_user() of dvb_usercopy():

int dvb_usercopy(struct file *file,
                     unsigned int cmd, unsigned long arg,
                     int (*func)(struct file *file,
                     unsigned int cmd, void *arg))
{
        char    sbuf[128];
        void    *mbuf = NULL;
        void    *parg = NULL;
        int     err  = -EINVAL;

        /*  Copy arguments into temp kernel buffer  */
        switch (_IOC_DIR(cmd)) {
        case _IOC_NONE:
                /*
                 * For this command, the pointer is actually an integer
                 * argument.
                 */
                parg = (void *) arg;
                break;
        case _IOC_READ: /* some v4l ioctls are marked wrong ... */
        case _IOC_WRITE:
        case (_IOC_WRITE | _IOC_READ):
                if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
                        parg = sbuf;
                } else {
                        /* too big to allocate from stack */
                        mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
                        if (NULL == mbuf)
                                return -ENOMEM;
                        parg = mbuf;
                }

                err = -EFAULT;
                if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))   // here
                        goto out;
                break;
        }
  1. close() the fd in the thread that open()ed the dvr0 node. Then dvb_dvr_release() is called, and dvbdev->users-- and wake_up(&dvbdev->wait_queue) are executed to wake up the dvb_dmxdev_release() function, which is the .disconnect flow.

  2. In the .disconnect flow, dvb_dmxdev_release() function, vfree(dmxdev->filter) is executed.

  3. Release userfaultfd from the demux0 ioctl thread that set userfaultfd. This will cause the UAF to occur by reading the dmxdev->filter address you just released from .disconnect. UAF can now be used in all cases of dvb_demux_do_ioctl(), and even LPE is possible when linked with eBPF.

Download Tool