[PATCH] media: dvb-core: pesfilter shouldn't be set when feed is uninitialized

Edward Adam Davis posted 1 patch 7 hours ago
drivers/media/dvb-core/dvb_demux.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
[PATCH] media: dvb-core: pesfilter shouldn't be set when feed is uninitialized
Posted by Edward Adam Davis 7 hours ago
syzbot reported a uninit-value bug in [1].

When dmx_ts_feed_set() fails, the feed is not properly initialized. This
includes the feed not being added to the demux's feed_list and ts_type,
pes_type, etc., not being set. Under these circumstances, it is illogical
to determine whether to set the pesfilter in dvbdmx_release_ts_feed()
based on the uninitialized members ts_type and pes_type of the feed.

Since dvb_demux_feed_del() checks whether the feed has been successfully
added to the demux's feed_list, it can be confirmed that the feed has
been correctly initialized when it is added to the demux's feed_list.
A return value is added to dvb_demux_feed_del().
When the feed is not added to the feed_list, it is considered that the
feed has not yet been initialized, and when releasing the feed, it will
no longer determine whether to update the pesfilter based on its members.

[1]
BUG: KMSAN: uninit-value in dvbdmx_release_ts_feed+0x198/0x290 drivers/media/dvb-core/dvb_demux.c:858
 dvbdmx_release_ts_feed+0x198/0x290 drivers/media/dvb-core/dvb_demux.c:858
 dvb_dmxdev_start_feed drivers/media/dvb-core/dmxdev.c:-1 [inline]
 dvb_dmxdev_filter_start+0x1187/0x1af0 drivers/media/dvb-core/dmxdev.c:766

Uninit was created at:
 dvb_dmx_init+0x121/0x930 drivers/media/dvb-core/dvb_demux.c:1253
 vidtv_bridge_dmx_init drivers/media/test-drivers/vidtv/vidtv_bridge.c:334 [inline]

Reported-by: syzbot+01d4620886bee3db0e74@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=01d4620886bee3db0e74
Tested-by: syzbot+01d4620886bee3db0e74@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
 drivers/media/dvb-core/dvb_demux.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index 290fc7961647..669ce8b95ad5 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -670,18 +670,22 @@ static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
 	spin_unlock_irq(&feed->demux->lock);
 }
 
-static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
+static int dvb_demux_feed_del(struct dvb_demux_feed *feed)
 {
+	int ret;
 	spin_lock_irq(&feed->demux->lock);
 	if (!(dvb_demux_feed_find(feed))) {
 		pr_err("%s: feed not in list (type=%x state=%x pid=%x)\n",
 		       __func__, feed->type, feed->state, feed->pid);
+		ret = -EINVAL;
 		goto out;
 	}
 
 	list_del(&feed->list_head);
+	ret = 0;
 out:
 	spin_unlock_irq(&feed->demux->lock);
+	return ret;
 }
 
 static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
@@ -840,6 +844,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
 {
 	struct dvb_demux *demux = (struct dvb_demux *)dmx;
 	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	int ret;
 
 	mutex_lock(&demux->mutex);
 
@@ -851,11 +856,12 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
 	feed->state = DMX_STATE_FREE;
 	feed->filter->state = DMX_STATE_FREE;
 
-	dvb_demux_feed_del(feed);
+	ret = dvb_demux_feed_del(feed);
 
 	feed->pid = 0xffff;
 
-	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_PES_OTHER)
+	if (!ret && feed->ts_type & TS_DECODER &&
+	    feed->pes_type < DMX_PES_OTHER)
 		demux->pesfilter[feed->pes_type] = NULL;
 
 	mutex_unlock(&demux->mutex);
-- 
2.43.0