[Linux Kernel Bugs] KASAN: slab-use-after-free Write in dvb_device_open and 6 other issues in dvb subsystem

5 views
Skip to first unread message

Jiaming Zhang

unread,
4:03 AM (19 hours ago) 4:03 AM
to mch...@kernel.org, hverkui...@kernel.org, tg...@kernel.org, mi...@kernel.org, Darshan Rathod, linux-...@vger.kernel.org, linux...@vger.kernel.org, syzk...@googlegroups.com
Dear Linux kernel developers and maintainers,

We are writing to report 7 issues discovered in the dvb subsystem with
our generated syzkaller specifications. Below are the details of these
issues:

(1) KASAN: slab-use-after-free Write in dvb_device_open (reproducer: c, syz)
(2) KASAN: slab-use-after-free Read in dvb_frontend_release (reproducer: syz)
(3) possible deadlock in dvb_dvr_release (reproducer: c, syz)
(4) KASAN: slab-use-after-free Read in dvb_frontend_thread
(5) KFENCE: use-after-free read in dvb_frontend_release
(6) WARNING: still has locks held in _dmxdev_lock
(7) WARNING: bad unlock balance in _dmxdev_unlock

Here is our analysis:

## (1) KASAN: slab-use-after-free Write in dvb_device_open

The root cause is double put. In dvb_device_open(), the refcount is
decreased (via put) when the open operation fails [1]. However, in
dvb_frontend_open(), put will also be called in dvb_generic_release()
if dvb_frontend_start() failed. Such process can lead to double put
and use-after-free.

[1] https://elixir.bootlin.com/linux/v6.19-rc4/source/drivers/media/dvb-core/dvbdev.c#L113

## (2) KASAN: slab-use-after-free Read in dvb_frontend_release

The root cause is that in concurrent scenarios, the kernel attempts to
access dvbdev->users after dvbdev has already been freed [2].

[2] https://elixir.bootlin.com/linux/v6.19-rc4/source/drivers/media/dvb-core/dvb_frontend.c#L2916

## (3) possible deadlock in dvb_dvr_release

The root cause is lock imbalance. Call chain is as follows:

dvb_vb2_dqbuf() ->
vb2_core_dqbuf() ->
__vb2_get_done_vb() ->
__vb2_wait_for_done_vb() ->
_dmxdev_lock() (call_void_qop(q, wait_finish, q)) ->
mutex_lock()

ctx->mutex is locked during this process, but if the return value of
vb2_core_dqbuf() is not zero, ctx->mutex will not be unlocked [3].
When the task exits and calls dvb_dvr_release(), the function attempts
to acquire dmxdev->lock, lockdep detects that ctx->mutex is still
held, violating the locking order and reporting possible deadlock.

[3] https://elixir.bootlin.com/linux/v6.19-rc4/source/drivers/media/dvb-core/dvb_vb2.c#L415-L419

A potentail solution is to protect vb2_core_dqbuf() with mutex, e.g.

```
int dvb_vb2_dqbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
{
unsigned long flags;
int ret;

+ mutex_lock(&ctx->mutex);
ret = vb2_core_dqbuf(&ctx->vb_q, &b->index, b, ctx->nonblocking);
+ mutex_unlock(&ctx->mutex);
if (ret) ...
}
```

If this solution is acceptable, we would be happy to submit a patch :)

## Other issues

Unfortunately we do not have reproducers for other issues currently.
We have attached kernel console output to help with analysis and offer
our preliminary findings:

(4) KASAN: slab-use-after-free Read in dvb_frontend_thread: in
concurrent scenarios, kernel accesses fepriv->wait_queue after dvbdev
is freed [4]. Would adding a refcount for dvbdec to fix this?

(5) KFENCE: use-after-free read in dvb_frontend_release: similar to (2).

(6) WARNING: still has locks held in _dmxdev_lock: it seems a branch
in dvb_dvr_do_ioctl() might be acquiring a lock but failing to release
it?

(7) WARNING: bad unlock balance in _dmxdev_unlock: in call chain like
dvb_dvr_do_ioctl() -> dvb_vb2_dqbuf(), kernel misjudge lock state and
attempt to unlock an already unlocked lock?

[4] https://elixir.bootlin.com/linux/v6.19-rc4/source/drivers/media/dvb-core/dvb_frontend.c#L682-L685

You can refer to [5] to reproduce issues using syz programs. We also
provide our generated specs to help with running of syz program.

[5] https://github.com/google/syzkaller/blob/master/docs/reproducing_crashes.md#using-a-syz-reproducer

Please let me know if any further information is required.

Best Regards,
Jiaming Zhang
[deadlock-dvb_dvr_release] repro.c
[kasan-suaf-write-dvb_device_open] kernel.log
[kasan-suaf-write-dvb_device_open] report
[kasan-suaf-write-dvb_device_open] repro.c
[kasan-suaf-write-dvb_device_open] repro.syz
[kfence-uaf-read-dvb_frontend_release] kernel.log
[kfence-uaf-read-dvb_frontend_release] report
[warning-_dmxdev_lock] kernel.log
[warning-_dmxdev_lock] report
[warning-_dmxdev_unlock] report
[warning-_dmxdev_unlock] kernel.log
.config
syzkaller-ac3c71e7.patch
[kasan-suaf-read-dvb_frontend_release] repro.syz
[deadlock-dvb_dvr_release] report
[deadlock-dvb_dvr_release] repro.syz
[deadlock-dvb_dvr_release] kernel.log
[kasan-suaf-read-dvb_frontend_release] report
[kasan-suaf-read-dvb_frontend_release] kernel.log
[kasan-suaf-read-dvb_frontend_thread] kernel.log
[kasan-suaf-read-dvb_frontend_thread] report
Reply all
Reply to author
Forward
0 new messages