[PATCH] media: vidtv: Fix a wild pointer dereference in vidtv_channel_pmt_match_sections()

From: Zhou Qingyang
Date: Tue Nov 30 2021 - 11:39:55 EST


In vidtv_channel_pmt_match_sections(), vidtv_psi_pmt_stream_init() is
assigned to tail and &tail->descriptor is used in
vidtv_psi_desc_assign(). There is a dereference of &tail->descriptor
in vidtv_psi_desc_assign(), which could lead to a wild pointer
dereference onfailure of vidtv_psi_pmt_stream_init().

Fix this bug by adding a check of tail.

This bug was found by a static analyzer. The analysis employs
differential checking to identify inconsistent security operations
(e.g., checks or kfrees) between two code paths and confirms that the
inconsistent operations are not recovered in the current function or
the callers, so they constitute bugs.

Note that, as a bug found by static analysis, it can be a false
positive or hard to trigger. Multiple researchers have cross-reviewed
the bug.

Builds with CONFIG_DVB_VIDTV=m show no new warnings,
and our static analyzer no longer warns about this code.

Fixes: f90cf6079bf6 ("media: vidtv: add a bridge driver")
Signed-off-by: Zhou Qingyang <zhou1615@xxxxxxx>
---
drivers/media/test-drivers/vidtv/vidtv_channel.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/media/test-drivers/vidtv/vidtv_channel.c b/drivers/media/test-drivers/vidtv/vidtv_channel.c
index 7838e6272712..f2faa5504642 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_channel.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_channel.c
@@ -318,6 +318,10 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
struct vidtv_psi_table_pmt_stream *s = NULL;
struct vidtv_channel *cur_chnl = channels;
struct vidtv_psi_desc *desc = NULL;
+ struct vidtv_mux *m = container_of(&channels,
+ struct vidtv_mux,
+ channels);
+
u16 e_pid; /* elementary stream pid */
u16 curr_id;
u32 j;
@@ -341,6 +345,13 @@ vidtv_channel_pmt_match_sections(struct vidtv_channel *channels,
tail = vidtv_psi_pmt_stream_init(tail,
s->type,
e_pid);
+
+ if (!tail) {
+ vidtv_psi_pmt_stream_destroy(head);
+ dev_warn_ratelimited(m->dev,
+ "No enough memory for vidtv_psi_pmt_stream_init");
+ return;
+ }

if (!head)
head = tail;
--
2.25.1