Skip to content

Commit 972e63e

Browse files
committed
media: dvbdev: prevent the risk of out of memory access
The dvbdev contains a static variable used to store dvb minors. The behavior of it depends if CONFIG_DVB_DYNAMIC_MINORS is set or not. When not set, dvb_register_device() won't check for boundaries, as it will rely that a previous call to dvb_register_adapter() would already be enforcing it. On a similar way, dvb_device_open() uses the assumption that the register functions already did the needed checks. This can be fragile if some device ends using different calls. This also generate warnings on static check analysers like Coverity. So, add explicit guards to prevent potential risk of OOM issues. Fixes: 5dd3f30 ("V4L/DVB (9361): Dynamic DVB minor allocation") Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
1 parent e6a3ea8 commit 972e63e

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

drivers/media/dvb-core/dvbdev.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,15 @@ static DECLARE_RWSEM(minor_rwsem);
8686
static int dvb_device_open(struct inode *inode, struct file *file)
8787
{
8888
struct dvb_device *dvbdev;
89+
unsigned int minor = iminor(inode);
90+
91+
if (minor >= MAX_DVB_MINORS)
92+
return -ENODEV;
8993

9094
mutex_lock(&dvbdev_mutex);
9195
down_read(&minor_rwsem);
92-
dvbdev = dvb_minors[iminor(inode)];
96+
97+
dvbdev = dvb_minors[minor];
9398

9499
if (dvbdev && dvbdev->fops) {
95100
int err = 0;
@@ -525,7 +530,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
525530
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
526531
if (!dvb_minors[minor])
527532
break;
528-
if (minor == MAX_DVB_MINORS) {
533+
if (minor >= MAX_DVB_MINORS) {
529534
if (new_node) {
530535
list_del(&new_node->list_head);
531536
kfree(dvbdevfops);
@@ -540,6 +545,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
540545
}
541546
#else
542547
minor = nums2minor(adap->num, type, id);
548+
if (minor >= MAX_DVB_MINORS) {
549+
dvb_media_device_free(dvbdev);
550+
list_del(&dvbdev->list_head);
551+
kfree(dvbdev);
552+
*pdvbdev = NULL;
553+
mutex_unlock(&dvbdev_register_lock);
554+
return ret;
555+
}
543556
#endif
544557
dvbdev->minor = minor;
545558
dvb_minors[minor] = dvb_device_get(dvbdev);

0 commit comments

Comments
 (0)