]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
media: dvb-core: fix wrong reinitialization of ringbuffer on reopen
authorJens Axboe <axboe@kernel.dk>
Tue, 24 Feb 2026 18:51:16 +0000 (11:51 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 Feb 2026 20:39:00 +0000 (12:39 -0800)
dvb_dvr_open() calls dvb_ringbuffer_init() when a new reader opens the
DVR device.  dvb_ringbuffer_init() calls init_waitqueue_head(), which
reinitializes the waitqueue list head to empty.

Since dmxdev->dvr_buffer.queue is a shared waitqueue (all opens of the
same DVR device share it), this orphans any existing waitqueue entries
from io_uring poll or epoll, leaving them with stale prev/next pointers
while the list head is reset to {self, self}.

The waitqueue and spinlock in dvr_buffer are already properly
initialized once in dvb_dmxdev_init().  The open path only needs to
reset the buffer data pointer, size, and read/write positions.

Replace the dvb_ringbuffer_init() call in dvb_dvr_open() with direct
assignment of data/size and a call to dvb_ringbuffer_reset(), which
properly resets pread, pwrite, and error with correct memory ordering
without touching the waitqueue or spinlock.

Cc: stable@vger.kernel.org
Fixes: 34731df288a5f ("V4L/DVB (3501): Dmxdev: use dvb_ringbuffer")
Reported-by: syzbot+ab12f0c08dd7ab8d057c@syzkaller.appspotmail.com
Tested-by: syzbot+ab12f0c08dd7ab8d057c@syzkaller.appspotmail.com
Link: https://lore.kernel.org/all/698a26d3.050a0220.3b3015.007d.GAE@google.com/
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/media/dvb-core/dmxdev.c

index 7cfed24054d06a7b495817bacbf832c035ff19a2..3c8bc75e4d6c80c0a4420bfbebed9e4f2a88f1e5 100644 (file)
@@ -168,7 +168,9 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
                        mutex_unlock(&dmxdev->mutex);
                        return -ENOMEM;
                }
-               dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+               dmxdev->dvr_buffer.data = mem;
+               dmxdev->dvr_buffer.size = DVR_BUFFER_SIZE;
+               dvb_ringbuffer_reset(&dmxdev->dvr_buffer);
                if (dmxdev->may_do_mmap)
                        dvb_vb2_init(&dmxdev->dvr_vb2_ctx, "dvr",
                                     &dmxdev->mutex,