Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2022-41218 — CVE-2022-41218에 대한 취약점 세부 정보 | Kitploit
도구/GitHubGitHub/tobey123/cve-2022-41218
Vulnerability AnalysisExploitationBinary Exploitation
GitHubtobey123/cve-2022-41218

CVE-2022-41218

CVE-2022-41218에 대한 취약점 세부 정보

저장소 보기
43년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Introduction

이 취약점은 drivers/media/dvb-core/dmxdev.c에서 발생하는 경쟁 조건 취약점입니다. 따라서 이 dmxdev를 사용하는 usb 장치 드라이버에서 경쟁 조건이 발생할 수 있습니다.

이 취약점은 3개의 UAF를 트리거하는 데 사용될 수 있습니다.

Vulnerability

1. vmalloc UAF 쓰기

먼저, 익스플로잇 순서는 다음과 같습니다(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!!

root@kitploit:~
상세한 익스플로잇 흐름은 다음과 같습니다:

1. 디바이스 노드 중 dvr0에 대해 open()을 호출합니다. 이는 dvb_dvr_open()을 호출하여 `dvbdev->users++`가 실행되도록 합니다.
   이 경우, usb 디바이스를 제거하여 ttusb_dec_disconnect()가 실행되면 `wait_event(dmxdev->dvr_dvbdev->wait_queue, …)` 조건이 포착됩니다.

2. USB 디바이스를 물리적으로 제거합니다.
   이 경우, ttusb_dec_disconnect() 함수가 실행되는 동안 `wait_event(dmxdev->dvr_dvbdev->wait_queue, …)`에서 대기합니다.

3. demux0 노드에 대해 open()을 호출하여 dvb_demux_open() 함수가 호출되도록 합니다.
   이 함수도 단계 1의 dvb_dvr_open() 함수와 유사하게 `dvbdev->users++`를 실행합니다.
   그러나 현재 대기 중인 dvb_dmxdev_release() 함수가 이미 `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);
}

그런 다음 demux0에서 ioctl()을 호출합니다. 호출 시, 세 번째 인자는 userfaultfd(또는 FUSE fs)에 의해 설정된 사용자 공간 주소를 제출합니다. 이제 ioctl이 실행되는 동안 dvb_usercopy()의 copy_from_user()에서 멈추게 됩니다:``` 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;

root@kitploit:~
    /*  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;
    }
root@kitploit:~
4. dvr0 노드를 open()한 스레드에서 fd를 close()합니다.
그러면 dvb_dvr_release()가 호출되고, `dvbdev->users--`와 `wake_up(&dvbdev->wait_queue)`가 실행되어 .disconnect 흐름인 dvb_dmxdev_release() 함수를 깨웁니다.

5. .disconnect 흐름에서 dvb_dmxdev_release() 함수는 `vfree(dmxdev->filter)`를 실행합니다.

6. userfaultfd를 설정한 demux0 ioctl 스레드에서 userfaultfd를 해제합니다.
이로 인해 .disconnect에서 방금 해제한 `dmxdev->filter` 주소를 읽어 UAF가 발생합니다.
이제 UAF는 dvb_demux_do_ioctl()의 모든 경우에 사용될 수 있으며, eBPF와 연결하면 LPE도 가능합니다.

커널 로그는 다음과 같습니다:

[ 155.774326] BUG: unable to handle page fault for address: ffff888105f8c000
[ 155.774331] #PF: supervisor read access in kernel mode
[ 155.774333] #PF: error_code(0x0000) - not-present page

root@kitploit:~
[   83.990720] BUG: unable to handle page fault for address: ffffc900013c5060
[   83.990733] #PF: supervisor read access in kernel mode
[   83.990739] #PF: error_code(0x0000) - not-present page
[   83.990744] PGD 100000067 P4D 100000067 PUD 1001dd067 PMD 1078fc067 PTE 0
[   83.990760] Oops: 0000 [#1] PREEMPT SMP NOPTI
[   83.990768] CPU: 2 PID: 2580 Comm: exploit Not tainted 6.0.0-rc2+ #3
[   83.990776] Hardware name: Gigabyte Technology Co., Ltd. B460MDS3H/B460M DS3H, BIOS F3 05/27/2020
[   83.990781] RIP: 0010:dvb_demux_do_ioctl+0x22/0x5b0 [dvb_core]
[   83.990809] Code: 00 00 00 00 0f 1f 40 00 0f 1f 44 00 00 55 48 89 e5 41 57 49 89 d7 41 56 41 55 41 54 53 89 f3 48 84
[   83.990816] RSP: 0018:ffffc90001a3fd10 EFLAGS: 00010282
[   83.990824] RAX: 0000000000000000 RBX: 00000000403c6f2b RCX: ffffffffc051c520
[   83.990830] RDX: ffffc90001a3fd80 RSI: 00000000403c6f2b RDI: ffff88810c4adc00
[   83.990835] RBP: ffffc90001a3fd58 R08: 0000000000000000 R09: 0000000000000000
[   83.990840] R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffff2
[   83.990845] R13: ffffc900013c5000 R14: ffff88810c4adc00 R15: ffffc90001a3fd80
[   83.990850] FS:  00007f0c4fdd7640(0000) GS:ffff88844ea80000(0000) knlGS:0000000000000000
[   83.990857] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   83.990863] CR2: ffffc900013c5060 CR3: 000000010b31e001 CR4: 00000000007706e0
[   83.990869] PKRU: 55555554
[   83.990873] Call Trace:
[   83.990877]  <TASK>
[   83.990886]  dvb_usercopy+0x55/0x1a0 [dvb_core]
[   83.990907]  ? dvb_dmxdev_filter_start+0x3b0/0x3b0 [dvb_core]
[   83.990932]  dvb_demux_ioctl+0x15/0x20 [dvb_core]
[   83.990951]  __x64_sys_ioctl+0x92/0xd0
[   83.990965]  do_syscall_64+0x59/0x90
[   83.990973]  ? debug_smp_processor_id+0x17/0x20
[   83.990984]  ? fpregs_assert_state_consistent+0x2a/0x50
[   83.990995]  ? exit_to_user_mode_prepare+0x49/0x1a0
[   83.991007]  ? syscall_exit_to_user_mode+0x26/0x50
[   83.991016]  ? __x64_sys_write+0x19/0x20
[   83.991024]  ? do_syscall_64+0x69/0x90
[   83.991030]  ? irqentry_exit_to_user_mode+0x9/0x20
[   83.991039]  ? irqentry_exit+0x3b/0x50
[   83.991048]  ? exc_page_fault+0x87/0x180
[   83.991056]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[   83.991068] RIP: 0033:0x454b7f
[   83.991075] Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 40
[   83.991081] RSP: 002b:00007f0c4fdd7150 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[   83.991090] RAX: ffffffffffffffda RBX: 00007f0c4fdd7640 RCX: 0000000000454b7f
[   83.991095] RDX: 00007f0c50dda000 RSI: 00000000403c6f2b RDI: 0000000000000005
[   83.991100] RBP: 00007f0c4fdd71d0 R08: 0000000000000000 R09: 0000000000000000
[   83.991104] R10: 000000000000000a R11: 0000000000000246 R12: 00007f0c4fdd7640
[   83.991109] R13: 0000000000000000 R14: 000000000041ba00 R15: 00007f0c4f5d7000
[   83.991118]  </TASK>
[   83.991121] Modules linked in: snd_usb_audio usbhid hid snd_usbmidi_lib ttusb_dec ttusbdecfe dvb_core mc snd_sof_pca
[   83.991249]  sysfillrect rapl sysimgblt snd intel_cstate mei_me soundcore ee1004 mei gigabyte_wmi wmi_bmof serial_mt
[   83.991333] CR2: ffffc900013c5060
[   83.991339] ---[ end trace 0000000000000000 ]---
[   83.991344] RIP: 0010:dvb_demux_do_ioctl+0x22/0x5b0 [dvb_core]
[   83.991366] Code: 00 00 00 00 0f 1f 40 00 0f 1f 44 00 00 55 48 89 e5 41 57 49 89 d7 41 56 41 55 41 54 53 89 f3 48 84
[   83.991372] RSP: 0018:ffffc90001a3fd10 EFLAGS: 00010282
[   83.991378] RAX: 0000000000000000 RBX: 00000000403c6f2b RCX: ffffffffc051c520
[   83.991383] RDX: ffffc90001a3fd80 RSI: 00000000403c6f2b RDI: ffff88810c4adc00
[   83.991387] RBP: ffffc90001a3fd58 R08: 0000000000000000 R09: 0000000000000000
[   83.991392] R10: 0000000000000000 R11: 0000000000000000 R12: 00000000fffffff2
[   83.991396] R13: ffffc900013c5000 R14: ffff88810c4adc00 R15: ffffc90001a3fd80
[   83.991401] FS:  00007f0c4fdd7640(0000) GS:ffff88844ea80000(0000) knlGS:0000000000000000
[   83.991407] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   83.991412] CR2: ffffc900013c5060 CR3: 000000010b31e001 CR4: 00000000007706e0
[   83.991417] PKRU: 55555554
```
## 2. 임의 주소 실행을 허용하는 UAF
먼저, 익스플로잇의 순서는 다음과 같습니다:```
                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()
                                                        4. dvb_dvr_release()
5. dvb_unregister_device(dmxdev->dvbdev)
   dvb_free_device()
   kfree (dvbdev->fops)
                                                                                                6. close(demux0)
                                                                                                   __x64_sys_close()
                                                                                                   close_fd()
                                                                                                   filp_close()
                                                                                                   filp->f_op->flush(filp, id);  <- UAF!!
```
상세한 익스플로잇 흐름은 다음과 같습니다:

1 ~ 4. 1~4의 순서는 첫 번째 취약점과 동일합니다.

5. .disconnect 흐름에서 `dvb_unregister_device(dmxdev->dvbdev) -> dvb_free_device() -> kfree (dvbdev->fops)`가 실행됩니다.
여기서 kfree()된 `dvbdev->fops`는 UAF 취약점의 대상입니다.

6. demux0 노드를 open()한 스레드에서 demux0 fd를 close()합니다.
실제로 demux0와 같은 dvb 장치 노드를 열 때는 dvb_XXX_open()이 아닌 `dvb_device_open()`이 먼저 호출됩니다:```
static int dvb_device_open(struct inode *inode, struct file *file)
{
        struct dvb_device *dvbdev;

        mutex_lock(&dvbdev_mutex);
        down_read(&minor_rwsem);
        dvbdev = dvb_minors[iminor(inode)];

        if (dvbdev && dvbdev->fops) {
                int err = 0;
                const struct file_operations *new_fops;

                new_fops = fops_get(dvbdev->fops);
                if (!new_fops)
                        goto fail;
                file->private_data = dvbdev;
                replace_fops(file, new_fops);    // replace fops here.
                if (file->f_op->open)
                        err = file->f_op->open(inode, file);    // call dvb_XXX_open()
                up_read(&minor_rwsem);
                mutex_unlock(&dvbdev_mutex);
                return err;
        }
fail:
        up_read(&minor_rwsem);
        mutex_unlock(&dvbdev_mutex);
        return -ENODEV;
}
```
위 함수가 호출된 후, `replace_fops(file, new_fops);`를 통해 `file->f_op`가 `dvbdev->fops`로 대체됩니다.  
이 `dvbdev->fops`는 단계 5에서 설명된 대로 이 UAF 취약점의 대상입니다.

흐름으로 돌아와서, `close(demux0)`가 호출되었기 때문에 close() 시스템 콜은 `__x64_sys_close() -> close_fd() -> filp_close()` 순서로 실행됩니다:```
int filp_close(struct file *filp, fl_owner_t id)
{
        int retval = 0;

        if (!file_count(filp)) {
                printk(KERN_ERR "VFS: Close: file count is 0\n");
                return 0;
        }

        if (filp->f_op->flush)
                retval = filp->f_op->flush(filp, id);    // UAF!!

        if (likely(!(filp->f_mode & FMODE_PATH))) {
                dnotify_flush(filp, id);
                locks_remove_posix(filp, id);
        }
        fput(filp);
        return retval;
}
```
위 함수에서 `filp->f_op->flush(filp, id);`가 호출되며, 이 `f_op`가 5단계에서 kfree()된 fops이기 때문에 UAF가 발생합니다.
이는 kmalloc 힙 스프레이와 결합하여 원하는 주소를 실행할 수 있는 취약점이 됩니다.


다음은 KASAN 로그입니다:```
[  708.982899] ==================================================================
[  708.982921] BUG: KASAN: use-after-free in filp_close+0x119/0x140
[  708.982929] Read of size 8 at addr ffff888114bd4078 by task exploit2/2918

[  708.982933] CPU: 7 PID: 2918 Comm: exploit2 Not tainted 6.0.0-rc2+ #4
[  708.982936] Hardware name: Gigabyte Technology Co., Ltd. B460MDS3H/B460M DS3H, BIOS F3 05/27/2020
[  708.982938] Call Trace:
[  708.982954]  <TASK>
[  708.982956]  dump_stack_lvl+0x49/0x63
[  708.982960]  print_report.cold+0x5e/0x5d9
[  708.982963]  ? filp_close+0x119/0x140
[  708.982966]  kasan_report+0xa0/0x120
[  708.982969]  ? filp_close+0x119/0x140
[  708.982972]  __asan_report_load8_noabort+0x14/0x20
[  708.982975]  filp_close+0x119/0x140
[  708.982978]  close_fd+0x75/0x90
[  708.982981]  __x64_sys_close+0x30/0x80
[  708.982984]  do_syscall_64+0x59/0x90
[  708.982987]  ? syscall_exit_to_user_mode+0x26/0x50
[  708.982990]  ? do_syscall_64+0x69/0x90
[  708.982994]  ? syscall_exit_to_user_mode+0x26/0x50
[  708.983017]  ? __do_sys_gettid+0x1b/0x30
[  708.983022]  ? do_syscall_64+0x69/0x90
[  708.983027]  ? exit_to_user_mode_prepare+0x49/0x1a0
[  708.983035]  ? irqentry_exit_to_user_mode+0x9/0x20
[  708.983041]  ? irqentry_exit+0x3b/0x50
[  708.983045]  ? exc_page_fault+0x72/0xf0
[  708.983050]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[  708.983072] RIP: 0033:0x45396b
[  708.983077] Code: 03 00 00 00 0f 05 48 3d 00 f0 ff ff 77 41 c3 48 83 ec 18 89 7c 24 0c e8 33 a9 02 00 8b 7c 24 0c 41 89 c0 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 81 a9 02 00 8b 44
[  708.983081] RSP: 002b:00007f55128b41a0 EFLAGS: 00000293 ORIG_RAX: 0000000000000003
[  708.983087] RAX: ffffffffffffffda RBX: 00007f55128b4640 RCX: 000000000045396b
[  708.983091] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000004
[  708.983094] RBP: 00007f55128b41d0 R08: 0000000000000000 R09: 0000000000000000
[  708.983097] R10: 0000000000000000 R11: 0000000000000293 R12: 00007f55128b4640
[  708.983100] R13: 0000000000000000 R14: 000000000041b3e0 R15: 00007f55120b4000
[  708.983107]  </TASK>

[  708.983130] Allocated by task 663:
[  708.983133]  kasan_save_stack+0x26/0x50
[  708.983137]  __kasan_kmalloc+0xae/0xe0
[  708.983140]  __kmalloc_node+0x185/0x420
[  708.983145]  memcg_alloc_slab_cgroups+0x8a/0x130
[  708.983149]  allocate_slab+0x389/0x4a0
[  708.983152]  ___slab_alloc+0x6c5/0xa50
[  708.983155]  __slab_alloc.constprop.0+0x5a/0xb0
[  708.983159]  kmem_cache_alloc+0x2e3/0x320
[  708.983162]  seq_open+0x57/0x160
[  708.983166]  kernfs_fop_open+0x4f0/0xc10
[  708.983171]  do_dentry_open+0x404/0xf80
[  708.983174]  vfs_open+0x9f/0xd0
[  708.983177]  path_openat+0xd58/0x3f60
[  708.983181]  do_filp_open+0x1b1/0x3e0
[  708.983184]  do_sys_openat2+0x132/0x450
[  708.983187]  __x64_sys_openat+0x128/0x210
[  708.983191]  do_syscall_64+0x59/0x90
[  708.983194]  entry_SYSCALL_64_after_hwframe+0x63/0xcd

[  708.983201] Freed by task 159:
[  708.983204]  kasan_save_stack+0x26/0x50
[  708.983207]  kasan_set_track+0x25/0x40
[  708.983211]  kasan_set_free_info+0x24/0x40
[  708.983215]  ____kasan_slab_free+0x176/0x1e0
[  708.983218]  __kasan_slab_free+0x12/0x20
[  708.983221]  slab_free_freelist_hook+0xd0/0x1a0
[  708.983224]  kfree+0x1ae/0x3e0
[  708.983227]  dvb_free_device.part.0+0x33/0x70 [dvb_core]
[  708.983241]  dvb_unregister_device+0x20/0x30 [dvb_core]
[  708.983248]  dvb_dmxdev_release+0x3ba/0x4e3 [dvb_core]
[  708.983255]  ttusb_dec_disconnect+0x3d8/0x499 [ttusb_dec]
[  708.983258]  usb_unbind_interface+0x187/0x7c0
[  708.983261]  device_remove+0x117/0x170
[  708.983264]  device_release_driver_internal+0x418/0x660
[  708.983266]  device_release_driver+0x12/0x20
[  708.983268]  bus_remove_device+0x28f/0x540
[  708.983270]  device_del+0x501/0xc30
[  708.983273]  usb_disable_device+0x2a5/0x660
[  708.983274]  usb_disconnect.cold+0x1f9/0x620
[  708.983277]  hub_event+0x16d3/0x3d20
[  708.983280]  process_one_work+0x778/0x11c0
[  708.983283]  worker_thread+0x544/0x1180
[  708.983285]  kthread+0x280/0x320
[  708.983286]  ret_from_fork+0x1f/0x30

[  708.983291] The buggy address belongs to the object at ffff888114bd4000
                which belongs to the cache kmalloc-512 of size 512
[  708.983293] The buggy address is located 120 bytes inside of
                512-byte region [ffff888114bd4000, ffff888114bd4200)

[  708.983297] The buggy address belongs to the physical page:
[  708.983298] page:000000009b45bbf6 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x114bd0
[  708.983301] head:000000009b45bbf6 order:3 compound_mapcount:0 compound_pincount:0
[  708.983303] flags: 0x17ffffc0010200(slab|head|node=0|zone=2|lastcpupid=0x1fffff)
[  708.983307] raw: 0017ffffc0010200 dead000000000100 dead000000000122 ffff888100042c80
[  708.983309] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000
[  708.983311] page dumped because: kasan: bad access detected

[  708.983313] Memory state around the buggy address:
[  708.983314]  ffff888114bd3f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  708.983316]  ffff888114bd3f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  708.983318] >ffff888114bd4000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  708.983320]                                                                 ^
[  708.983321]  ffff888114bd4080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  708.983323]  ffff888114bd4100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  708.983325] ==================================================================
[  708.983336] Disabling lock debugging due to kernel taint
```
## 3. slab UAF 쓰기
세 번째 slab UAF 취약점은 두 번째와 거의 동일합니다.
이것은 극히 미세한 경쟁 조건 시간 차이에서만 발생합니다.

익스플로잇의 순서는 다음과 같습니다:```
                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()
                                                        4. dvb_dvr_release()
5. dvb_unregister_device(dmxdev->dvbdev)
   dvb_free_device()
   kfree (dvbdev)
                                                                                                6. dvb_demux_release()
                                                                                                   dmxdev->dvbdev->users--;  <- UAF!!
```
상세한 익스플로잇 흐름은 다음과 같습니다:

1 ~ 4. 1-4의 순서는 첫 번째 취약점과 동일합니다.

5. 이번에는 `dvbdev->fops`가 아닌 `dvbdev`가 UAF 취약점의 대상입니다:```
void dvb_free_device(struct dvb_device *dvbdev)
{
        if (!dvbdev)
                return;

        kfree (dvbdev->fops);
        kfree (dvbdev);    // target
}
EXPORT_SYMBOL(dvb_free_device);
```
6. `close(demux0)`가 실행되면 `dvb_demux_release()` 함수가 호출되고, `dmxdev->dvbdev->users--;`에서 UAF 쓰기 취약점이 발생합니다.```
static int dvb_demux_release(struct inode *inode, struct file *file)
{
        struct dmxdev_filter *dmxdevfilter = file->private_data;
        struct dmxdev *dmxdev = dmxdevfilter->dev;
        int ret;

        ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);

        mutex_lock(&dmxdev->mutex);
        dmxdev->dvbdev->users--;    // here
        if (dmxdev->dvbdev->users == 1 && dmxdev->exit == 1) {
                mutex_unlock(&dmxdev->mutex);
                wake_up(&dmxdev->dvbdev->wait_queue);
        } else
                mutex_unlock(&dmxdev->mutex);

        return ret;
}
```
이 UAF 쓰기 취약점은 예를 들어 다른 구조체의 참조 횟수(refcount)를 감소시키는 데 사용될 수 있습니다.

# 취약점 범위
해당 취약점의 범위는 다음과 같습니다:

- drivers/media/usb/as102/as102_usb_drv.c
- drivers/media/usb/tm6000/tm6000-cards.c
- drivers/media/usb/pvrusb2/pvrusb2-dvb.c
- drivers/media/usb/au0828/au0828-core.c
- drivers/media/usb/cx231xx/cx231xx-cards.c
- drivers/media/usb/ttusb-dec/ttusb_dec.c
- drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
- drivers/media/usb/em28xx/em28xx-dvb.c
- drivers/media/usb/dvb-usb/cxusb.c
- drivers/media/usb/dvb-usb/dw2102.c
- drivers/media/usb/dvb-usb/dtt200u.c
- drivers/media/usb/dvb-usb/m920x.c
- drivers/media/usb/dvb-usb/dibusb-mb.c
- drivers/media/usb/dvb-usb/ttusb2.c
- drivers/media/usb/dvb-usb/pctv452e.c
- drivers/media/usb/dvb-usb/a800.c
- drivers/media/usb/dvb-usb/umt-010.c
- drivers/media/usb/dvb-usb/dtv5100.c
- drivers/media/usb/dvb-usb/dibusb-mc.c
- drivers/media/usb/dvb-usb/cinergyT2-core.c
- drivers/media/usb/dvb-usb/nova-t-usb2.c
- drivers/media/usb/dvb-usb/vp7045.c
- drivers/media/usb/dvb-usb/digitv.c
- drivers/media/usb/dvb-usb/gp8psk.c
- drivers/media/usb/dvb-usb/vp702x.c
- drivers/media/usb/dvb-usb/opera1.c
- drivers/media/usb/dvb-usb/technisat-usb2.c
- drivers/media/usb/dvb-usb/dib0700_core.c
- drivers/media/usb/dvb-usb/az6027.c
- drivers/media/usb/dvb-usb/af9005.c
- drivers/media/usb/dvb-usb-v2/au6610.c
- drivers/media/usb/dvb-usb-v2/zd1301.c
- drivers/media/usb/dvb-usb-v2/ce6230.c
- drivers/media/usb/dvb-usb-v2/ec168.c
- drivers/media/usb/dvb-usb-v2/gl861.c
- drivers/media/usb/dvb-usb-v2/dvbsky.c
- drivers/media/usb/dvb-usb-v2/az6007.c
- drivers/media/usb/dvb-usb-v2/lmedm04.c
- drivers/media/usb/dvb-usb-v2/anysee.c
- drivers/media/usb/dvb-usb-v2/mxl111sf.c
- drivers/media/usb/dvb-usb-v2/af9015.c
- drivers/media/usb/dvb-usb-v2/rtl28xxu.c
- drivers/media/usb/dvb-usb-v2/af9035.c
- ...

# 참조
- https://lore.kernel.org/all/[email protected]/
- https://www.suse.com/security/cve/CVE-2022-41218.html
- https://www.openwall.com/lists/oss-security/2022/09/24/1
도구 다운로드