2021-11-30 16:39:55

by Zhou Qingyang

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

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 <[email protected]>
---
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



2021-12-02 13:42:32

by Hans Verkuil

[permalink] [raw]
Subject: Re: [PATCH] media: vidtv: Fix a wild pointer dereference in vidtv_channel_pmt_match_sections()

On 30/11/2021 17:39, Zhou Qingyang wrote:
> 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().

onfailure -> on failure

>
> 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 <[email protected]>
> ---
> 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);

I honestly can't tell if this is the right thing to do.

Daniel, can you take a look at this?

> + dev_warn_ratelimited(m->dev,
> + "No enough memory for vidtv_psi_pmt_stream_init");

No -> Not
Add newline at the end of the string.

> + return;
> + }
>
> if (!head)
> head = tail;
>

Regards,

Hans

2021-12-02 17:07:12

by Daniel Almeida

[permalink] [raw]
Subject: Re: [PATCH] media: vidtv: Fix a wild pointer dereference in vidtv_channel_pmt_match_sections()

Hi Zhou Qingyang, thanks for the patch.

Yes this is a real issue.

> +
> + if (!tail) {
> + vidtv_psi_pmt_stream_destroy(head);
> + dev_warn_ratelimited(m->dev,
> + "No enough memory for vidtv_psi_pmt_stream_init");
> + return;
> + }

Yes this is the right thing to do, as vidtv_psi_pmt_stream_destroy will
free the stream chain and all descriptors associated with it, if any.

By then aborting out of this function, we will have a PMT section
without any streams. This is OK if the allocation failed.

Reviewed-by Daniel Almeida <[email protected]>

Thanks,

-- Daniel