diff mbox series

media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()

Message ID YHaulytonFcW+lyZ@mwanda
State Superseded
Headers show
Series media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() | expand

Commit Message

Dan Carpenter April 14, 2021, 8:57 a.m. UTC
The bounds checking in avc_ca_pmt() is not strict enough.  It should
be checking "read_pos + 4" because it's reading 5 bytes.  If the
"es_info_length" is non-zero then it reads a 6th byte so there needs to
be an additional check for that.

I also added checks for the "write_pos".  I don't think these are
required because "read_pos" and "write_pos" are tied together so
checking one ought to be enough.  But they make the code easier to
understand for me.

The other problem is that "length" can be invalid.  It comes from
"data_length" in fdtv_ca_pmt().

Cc: stable@vger.kernel.org
Reported-by: Luo Likang <luolikang@nsfocus.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
This hardware isn't super common so there is no embargo.  Resending
through normal lists.

Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems
very suspicous.  Reading more than 4 bytes in the loop will lead to
shift wrapping.

 drivers/media/firewire/firedtv-avc.c | 14 +++++++++++---
 drivers/media/firewire/firedtv-ci.c  |  2 ++
 2 files changed, 13 insertions(+), 3 deletions(-)

Comments

Kees Cook April 19, 2021, 9:42 p.m. UTC | #1
On Wed, Apr 14, 2021 at 11:57:59AM +0300, Dan Carpenter wrote:
> The bounds checking in avc_ca_pmt() is not strict enough.  It should

> be checking "read_pos + 4" because it's reading 5 bytes.  If the

> "es_info_length" is non-zero then it reads a 6th byte so there needs to

> be an additional check for that.

> 

> I also added checks for the "write_pos".  I don't think these are

> required because "read_pos" and "write_pos" are tied together so

> checking one ought to be enough.  But they make the code easier to

> understand for me.

> 

> The other problem is that "length" can be invalid.  It comes from

> "data_length" in fdtv_ca_pmt().

> 

> Cc: stable@vger.kernel.org

> Reported-by: Luo Likang <luolikang@nsfocus.com>

> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>


Thanks for the report and the fix!

As a quick note on alternative mitigations, it seems that
CONFIG_UBSAN_BOUNDS would have caught this at runtime too. (i.e.
c->operand[]'s size is known at build time, so out of bounds
indexing should be detected.)

-Kees

> ---

> This hardware isn't super common so there is no embargo.  Resending

> through normal lists.

> 

> Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems

> very suspicous.  Reading more than 4 bytes in the loop will lead to

> shift wrapping.

> 

>  drivers/media/firewire/firedtv-avc.c | 14 +++++++++++---

>  drivers/media/firewire/firedtv-ci.c  |  2 ++

>  2 files changed, 13 insertions(+), 3 deletions(-)

> 

> diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c

> index 2bf9467b917d..71991f8638e6 100644

> --- a/drivers/media/firewire/firedtv-avc.c

> +++ b/drivers/media/firewire/firedtv-avc.c

> @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		read_pos += program_info_length;

>  		write_pos += program_info_length;

>  	}

> -	while (read_pos < length) {

> +	while (read_pos + 4 < length) {

> +		if (write_pos + 4 >= sizeof(c->operand) - 4) {

> +			ret = -EINVAL;

> +			goto out;

> +		}

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

> @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		c->operand[write_pos++] = es_info_length >> 8;

>  		c->operand[write_pos++] = es_info_length & 0xff;

>  		if (es_info_length > 0) {

> +			if (read_pos >= length) {

> +				ret = -EINVAL;

> +				goto out;

> +			}

>  			pmt_cmd_id = msg[read_pos++];

>  			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)

>  				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",

>  					pmt_cmd_id);

>  

> -			if (es_info_length > sizeof(c->operand) - 4 -

> -					     write_pos) {

> +			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||

> +			    es_info_length > length - read_pos) {

>  				ret = -EINVAL;

>  				goto out;

>  			}

> diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c

> index 9363d005e2b6..2d6992ac5dd6 100644

> --- a/drivers/media/firewire/firedtv-ci.c

> +++ b/drivers/media/firewire/firedtv-ci.c

> @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)

>  	} else {

>  		data_length = msg->msg[3];

>  	}

> +	if (data_length > sizeof(msg->msg) - 4)

> +		return -EINVAL;

>  

>  	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);

>  }

> -- 

> 2.30.2

> 


-- 
Kees Cook
Dan Carpenter July 19, 2021, 10:25 a.m. UTC | #2
This was marked as superseded in patchwork.  What are we going to apply
instead?

regards,
dan carpenter

On Wed, Apr 14, 2021 at 11:57:59AM +0300, Dan Carpenter wrote:
> The bounds checking in avc_ca_pmt() is not strict enough.  It should

> be checking "read_pos + 4" because it's reading 5 bytes.  If the

> "es_info_length" is non-zero then it reads a 6th byte so there needs to

> be an additional check for that.

> 

> I also added checks for the "write_pos".  I don't think these are

> required because "read_pos" and "write_pos" are tied together so

> checking one ought to be enough.  But they make the code easier to

> understand for me.

> 

> The other problem is that "length" can be invalid.  It comes from

> "data_length" in fdtv_ca_pmt().

> 

> Cc: stable@vger.kernel.org

> Reported-by: Luo Likang <luolikang@nsfocus.com>

> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

> ---

> This hardware isn't super common so there is no embargo.  Resending

> through normal lists.

> 

> Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems

> very suspicous.  Reading more than 4 bytes in the loop will lead to

> shift wrapping.

> 

>  drivers/media/firewire/firedtv-avc.c | 14 +++++++++++---

>  drivers/media/firewire/firedtv-ci.c  |  2 ++

>  2 files changed, 13 insertions(+), 3 deletions(-)

> 

> diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c

> index 2bf9467b917d..71991f8638e6 100644

> --- a/drivers/media/firewire/firedtv-avc.c

> +++ b/drivers/media/firewire/firedtv-avc.c

> @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		read_pos += program_info_length;

>  		write_pos += program_info_length;

>  	}

> -	while (read_pos < length) {

> +	while (read_pos + 4 < length) {

> +		if (write_pos + 4 >= sizeof(c->operand) - 4) {

> +			ret = -EINVAL;

> +			goto out;

> +		}

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

> @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		c->operand[write_pos++] = es_info_length >> 8;

>  		c->operand[write_pos++] = es_info_length & 0xff;

>  		if (es_info_length > 0) {

> +			if (read_pos >= length) {

> +				ret = -EINVAL;

> +				goto out;

> +			}

>  			pmt_cmd_id = msg[read_pos++];

>  			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)

>  				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",

>  					pmt_cmd_id);

>  

> -			if (es_info_length > sizeof(c->operand) - 4 -

> -					     write_pos) {

> +			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||

> +			    es_info_length > length - read_pos) {

>  				ret = -EINVAL;

>  				goto out;

>  			}

> diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c

> index 9363d005e2b6..2d6992ac5dd6 100644

> --- a/drivers/media/firewire/firedtv-ci.c

> +++ b/drivers/media/firewire/firedtv-ci.c

> @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)

>  	} else {

>  		data_length = msg->msg[3];

>  	}

> +	if (data_length > sizeof(msg->msg) - 4)

> +		return -EINVAL;

>  

>  	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);

>  }

> -- 

> 2.30.2
Greg Kroah-Hartman July 29, 2021, 10:32 a.m. UTC | #3
On Wed, Apr 14, 2021 at 11:57:59AM +0300, Dan Carpenter wrote:
> The bounds checking in avc_ca_pmt() is not strict enough.  It should

> be checking "read_pos + 4" because it's reading 5 bytes.  If the

> "es_info_length" is non-zero then it reads a 6th byte so there needs to

> be an additional check for that.

> 

> I also added checks for the "write_pos".  I don't think these are

> required because "read_pos" and "write_pos" are tied together so

> checking one ought to be enough.  But they make the code easier to

> understand for me.

> 

> The other problem is that "length" can be invalid.  It comes from

> "data_length" in fdtv_ca_pmt().

> 

> Cc: stable@vger.kernel.org

> Reported-by: Luo Likang <luolikang@nsfocus.com>

> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

> ---

> This hardware isn't super common so there is no embargo.  Resending

> through normal lists.

> 

> Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems

> very suspicous.  Reading more than 4 bytes in the loop will lead to

> shift wrapping.

> 

>  drivers/media/firewire/firedtv-avc.c | 14 +++++++++++---

>  drivers/media/firewire/firedtv-ci.c  |  2 ++

>  2 files changed, 13 insertions(+), 3 deletions(-)

> 

> diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c

> index 2bf9467b917d..71991f8638e6 100644

> --- a/drivers/media/firewire/firedtv-avc.c

> +++ b/drivers/media/firewire/firedtv-avc.c

> @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		read_pos += program_info_length;

>  		write_pos += program_info_length;

>  	}

> -	while (read_pos < length) {

> +	while (read_pos + 4 < length) {

> +		if (write_pos + 4 >= sizeof(c->operand) - 4) {

> +			ret = -EINVAL;

> +			goto out;

> +		}

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

>  		c->operand[write_pos++] = msg[read_pos++];

> @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

>  		c->operand[write_pos++] = es_info_length >> 8;

>  		c->operand[write_pos++] = es_info_length & 0xff;

>  		if (es_info_length > 0) {

> +			if (read_pos >= length) {

> +				ret = -EINVAL;

> +				goto out;

> +			}

>  			pmt_cmd_id = msg[read_pos++];

>  			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)

>  				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",

>  					pmt_cmd_id);

>  

> -			if (es_info_length > sizeof(c->operand) - 4 -

> -					     write_pos) {

> +			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||

> +			    es_info_length > length - read_pos) {

>  				ret = -EINVAL;

>  				goto out;

>  			}

> diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c

> index 9363d005e2b6..2d6992ac5dd6 100644

> --- a/drivers/media/firewire/firedtv-ci.c

> +++ b/drivers/media/firewire/firedtv-ci.c

> @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)

>  	} else {

>  		data_length = msg->msg[3];

>  	}

> +	if (data_length > sizeof(msg->msg) - 4)

> +		return -EINVAL;

>  

>  	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);

>  }

> -- 

> 2.30.2

> 


This patch seems to have gotten lost.  Any change of it getting applied?

thanks,

greg k-h
Salvatore Bonaccorso Aug. 16, 2021, 7:01 a.m. UTC | #4
Hi,

On Thu, Jul 29, 2021 at 12:32:21PM +0200, Greg KH wrote:
> On Wed, Apr 14, 2021 at 11:57:59AM +0300, Dan Carpenter wrote:

> > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > be an additional check for that.

> > 

> > I also added checks for the "write_pos".  I don't think these are

> > required because "read_pos" and "write_pos" are tied together so

> > checking one ought to be enough.  But they make the code easier to

> > understand for me.

> > 

> > The other problem is that "length" can be invalid.  It comes from

> > "data_length" in fdtv_ca_pmt().

> > 

> > Cc: stable@vger.kernel.org

> > Reported-by: Luo Likang <luolikang@nsfocus.com>

> > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

> > ---

> > This hardware isn't super common so there is no embargo.  Resending

> > through normal lists.

> > 

> > Oh, another thing is the data_length calculation in fdtv_ca_pmt() seems

> > very suspicous.  Reading more than 4 bytes in the loop will lead to

> > shift wrapping.

> > 

> >  drivers/media/firewire/firedtv-avc.c | 14 +++++++++++---

> >  drivers/media/firewire/firedtv-ci.c  |  2 ++

> >  2 files changed, 13 insertions(+), 3 deletions(-)

> > 

> > diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c

> > index 2bf9467b917d..71991f8638e6 100644

> > --- a/drivers/media/firewire/firedtv-avc.c

> > +++ b/drivers/media/firewire/firedtv-avc.c

> > @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

> >  		read_pos += program_info_length;

> >  		write_pos += program_info_length;

> >  	}

> > -	while (read_pos < length) {

> > +	while (read_pos + 4 < length) {

> > +		if (write_pos + 4 >= sizeof(c->operand) - 4) {

> > +			ret = -EINVAL;

> > +			goto out;

> > +		}

> >  		c->operand[write_pos++] = msg[read_pos++];

> >  		c->operand[write_pos++] = msg[read_pos++];

> >  		c->operand[write_pos++] = msg[read_pos++];

> > @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)

> >  		c->operand[write_pos++] = es_info_length >> 8;

> >  		c->operand[write_pos++] = es_info_length & 0xff;

> >  		if (es_info_length > 0) {

> > +			if (read_pos >= length) {

> > +				ret = -EINVAL;

> > +				goto out;

> > +			}

> >  			pmt_cmd_id = msg[read_pos++];

> >  			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)

> >  				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",

> >  					pmt_cmd_id);

> >  

> > -			if (es_info_length > sizeof(c->operand) - 4 -

> > -					     write_pos) {

> > +			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||

> > +			    es_info_length > length - read_pos) {

> >  				ret = -EINVAL;

> >  				goto out;

> >  			}

> > diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c

> > index 9363d005e2b6..2d6992ac5dd6 100644

> > --- a/drivers/media/firewire/firedtv-ci.c

> > +++ b/drivers/media/firewire/firedtv-ci.c

> > @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)

> >  	} else {

> >  		data_length = msg->msg[3];

> >  	}

> > +	if (data_length > sizeof(msg->msg) - 4)

> > +		return -EINVAL;

> >  

> >  	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);

> >  }

> > -- 

> > 2.30.2

> > 

> 

> This patch seems to have gotten lost.  Any change of it getting applied?


As far I can see there was then a version 2 of the patch, but that one
got list somewhere. Friendly ping on this thread :)

Regards,
Salvatore
Dan Carpenter Sept. 1, 2021, 10:40 a.m. UTC | #5
On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:
> The bounds checking in avc_ca_pmt() is not strict enough.  It should

> be checking "read_pos + 4" because it's reading 5 bytes.  If the

> "es_info_length" is non-zero then it reads a 6th byte so there needs to

> be an additional check for that.

> 

> I also added checks for the "write_pos".  I don't think these are

> required because "read_pos" and "write_pos" are tied together so

> checking one ought to be enough.  But they make the code easier to

> understand for me.  The check on write_pos is:

> 

> 	if (write_pos + 4 >= sizeof(c->operand) - 4) {

> 

> The first "+ 4" is because we're writing 5 bytes and the last " - 4"

> is to leave space for the CRC.

> 

> The other problem is that "length" can be invalid.  It comes from

> "data_length" in fdtv_ca_pmt().  Added a check in fdtv_ca_pmt() to

> prevent that.

> 

> Cc: stable@vger.kernel.org

> Reported-by: Luo Likang <luolikang@nsfocus.com>

> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

> ---

> RESEND: this patch got lost somehow.

> 


What the heck?  Someone on patchwork just marked this patch as obsolete
again!!!

Mauro can you figure out who's doing that and what's going on?  The
first time it was marked as obsolete then I asked about it twice, Greg
asked about it, and Salvatore Bonaccorso asked about it.  But all we
get are anonymous notifications from patchwork.  It's a bit frustrating.

regards,
dan carpenter
Salvatore Bonaccorso Sept. 12, 2021, 1:14 p.m. UTC | #6
Hi,

[linux-distros list dropped as not anymore relevant for embargo]

On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:
> On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:

> > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > be an additional check for that.

> > 

> > I also added checks for the "write_pos".  I don't think these are

> > required because "read_pos" and "write_pos" are tied together so

> > checking one ought to be enough.  But they make the code easier to

> > understand for me.  The check on write_pos is:

> > 

> > 	if (write_pos + 4 >= sizeof(c->operand) - 4) {

> > 

> > The first "+ 4" is because we're writing 5 bytes and the last " - 4"

> > is to leave space for the CRC.

> > 

> > The other problem is that "length" can be invalid.  It comes from

> > "data_length" in fdtv_ca_pmt().  Added a check in fdtv_ca_pmt() to

> > prevent that.

> > 

> > Cc: stable@vger.kernel.org

> > Reported-by: Luo Likang <luolikang@nsfocus.com>

> > Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

> > ---

> > RESEND: this patch got lost somehow.

> > 

> 

> What the heck?  Someone on patchwork just marked this patch as obsolete

> again!!!

> 

> Mauro can you figure out who's doing that and what's going on?  The

> first time it was marked as obsolete then I asked about it twice, Greg

> asked about it, and Salvatore Bonaccorso asked about it.  But all we

> get are anonymous notifications from patchwork.  It's a bit frustrating.


Someone knows what is going on here, i.e. what is the problem?

Regards,
Salvatore
Linus Torvalds Sept. 12, 2021, 6:26 p.m. UTC | #7
On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote:
>

> On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:

> > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:

> > > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > > be an additional check for that.

> > >

> > > I also added checks for the "write_pos".  I don't think these are

> > > required because "read_pos" and "write_pos" are tied together so

> > > checking one ought to be enough.


They may be in sync at a fixed offset, but the buffer length of the
read ("int length") is not in sync with the buffer length for the
write ("sizeof(c->operand)").

So I do think the write pos limit checking is actually necessary and needed.

> > > RESEND: this patch got lost somehow.

> >

> > What the heck?  Someone on patchwork just marked this patch as obsolete

> > again!!!


Can we please make sure patchwork has some logging so that that kind
of thing shows _who_ did this?

> Someone knows what is going on here, i.e. what is the problem?


Dan, can you just send that fix to me directly, with the fixed commit
message (see above), and we can close this.

That still leaves the "who closes things on patchwork" question, but
that's something I can't do anything about.

                Linus
Michael Ellerman Sept. 13, 2021, 2:50 a.m. UTC | #8
Linus Torvalds <torvalds@linuxfoundation.org> writes:
> On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote:

>>

>> On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:

>> > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:

>> > > The bounds checking in avc_ca_pmt() is not strict enough.  It should

>> > > be checking "read_pos + 4" because it's reading 5 bytes.  If the

>> > > "es_info_length" is non-zero then it reads a 6th byte so there needs to

>> > > be an additional check for that.

>> > >

>> > > I also added checks for the "write_pos".  I don't think these are

>> > > required because "read_pos" and "write_pos" are tied together so

>> > > checking one ought to be enough.

>

> They may be in sync at a fixed offset, but the buffer length of the

> read ("int length") is not in sync with the buffer length for the

> write ("sizeof(c->operand)").

>

> So I do think the write pos limit checking is actually necessary and needed.

>

>> > > RESEND: this patch got lost somehow.

>> >

>> > What the heck?  Someone on patchwork just marked this patch as obsolete

>> > again!!!

>

> Can we please make sure patchwork has some logging so that that kind

> of thing shows _who_ did this?


It's not easily visible in the web UI, but patchwork does log that sort
of info.

The v2 RESEND is:

 https://patchwork.linuxtv.org/project/linux-media/patch/20210816072721.GA10534@kili/

In the top right is the patch id (76352), you can then get the list of
events for that patch at:

  https://patchwork.linuxtv.org/api/events/?patch=76352

Which shows that hverkuil changed it to obsolete on 2021-09-01T10:16:43.

Presumably because they picked up the non-resend version, which was
marked as under-review around the same time:

  https://patchwork.linuxtv.org/api/events/?patch=74849

And then also visible on the above page, it was marked as accepted by
mchehab on 2021-09-03T13:06:16.

But I don't see the patch in linux-next, or in linux-media.git, so I'm
not sure where it's been accepted to?

cheers
Mauro Carvalho Chehab Sept. 13, 2021, 1:23 p.m. UTC | #9
Em Sun, 12 Sep 2021 11:26:10 -0700
Linus Torvalds <torvalds@linuxfoundation.org> escreveu:

> On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote:

> >

> > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:  

> > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:  

> > > > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > > > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > > > be an additional check for that.

> > > >

> > > > I also added checks for the "write_pos".  I don't think these are

> > > > required because "read_pos" and "write_pos" are tied together so

> > > > checking one ought to be enough.  

> 

> They may be in sync at a fixed offset, but the buffer length of the

> read ("int length") is not in sync with the buffer length for the

> write ("sizeof(c->operand)").

> 

> So I do think the write pos limit checking is actually necessary and needed.

> 

> > > > RESEND: this patch got lost somehow.  

> > >

> > > What the heck?  Someone on patchwork just marked this patch as obsolete

> > > again!!!  

> 

> Can we please make sure patchwork has some logging so that that kind

> of thing shows _who_ did this?


I've been wanting a feature like that on patchwork for years. Basically,
when there's more then a single person capable of accessing a patchwork
instance, there's no way to log who changed the status, nor to control who
can delegate a patch to someone else or not.

At least for me, touching patchwork is very hard, as the the entire login
logic, as well as the database model itself, is abstracted by Django. So,
I can't simply change a SQL insert clause there to add something else to
their logs nor to change the sent email that it is pushed when a patch
status changed.

I ended adding an internal log to indicate when I do some changes on my
patchwork instance via script a couple of years ago.

> > Someone knows what is going on here, i.e. what is the problem?  

> 

> Dan, can you just send that fix to me directly, with the fixed commit

> message (see above), and we can close this.


Feel free to add my:

	Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>


> 

> That still leaves the "who closes things on patchwork" question, but

> that's something I can't do anything about.


I'll double-check my scripts in order to identify if this came from
my side, and if so, fix them.

Thanks,
Mauro
Salvatore Bonaccorso Sept. 19, 2021, 6:45 p.m. UTC | #10
Hi Dan,

On Mon, Sep 13, 2021 at 03:23:02PM +0200, Mauro Carvalho Chehab wrote:
> Em Sun, 12 Sep 2021 11:26:10 -0700

> Linus Torvalds <torvalds@linuxfoundation.org> escreveu:

> 

> > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote:

> > >

> > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:  

> > > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:  

> > > > > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > > > > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > > > > be an additional check for that.

> > > > >

> > > > > I also added checks for the "write_pos".  I don't think these are

> > > > > required because "read_pos" and "write_pos" are tied together so

> > > > > checking one ought to be enough.  

> > 

> > They may be in sync at a fixed offset, but the buffer length of the

> > read ("int length") is not in sync with the buffer length for the

> > write ("sizeof(c->operand)").

> > 

> > So I do think the write pos limit checking is actually necessary and needed.

> > 

> > > > > RESEND: this patch got lost somehow.  

> > > >

> > > > What the heck?  Someone on patchwork just marked this patch as obsolete

> > > > again!!!  

> > 

> > Can we please make sure patchwork has some logging so that that kind

> > of thing shows _who_ did this?

> 

> I've been wanting a feature like that on patchwork for years. Basically,

> when there's more then a single person capable of accessing a patchwork

> instance, there's no way to log who changed the status, nor to control who

> can delegate a patch to someone else or not.

> 

> At least for me, touching patchwork is very hard, as the the entire login

> logic, as well as the database model itself, is abstracted by Django. So,

> I can't simply change a SQL insert clause there to add something else to

> their logs nor to change the sent email that it is pushed when a patch

> status changed.

> 

> I ended adding an internal log to indicate when I do some changes on my

> patchwork instance via script a couple of years ago.

> 

> > > Someone knows what is going on here, i.e. what is the problem?  

> > 

> > Dan, can you just send that fix to me directly, with the fixed commit

> > message (see above), and we can close this.

> 

> Feel free to add my:

> 

> 	Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>


I'm sorry for prodding again, I guess I'm becoming a bit annoying :-/

Dan, could you sent the patch with the above to Linus directly so it
can show up in at least 5.15-rc3? I guess it's now to late for
5.15-rc2.

Regards,
Salvatore
Salvatore Bonaccorso Oct. 11, 2021, 7:04 a.m. UTC | #11
Hi,

On Sun, Sep 19, 2021 at 08:45:42PM +0200, Salvatore Bonaccorso wrote:
> Hi Dan,

> 

> On Mon, Sep 13, 2021 at 03:23:02PM +0200, Mauro Carvalho Chehab wrote:

> > Em Sun, 12 Sep 2021 11:26:10 -0700

> > Linus Torvalds <torvalds@linuxfoundation.org> escreveu:

> > 

> > > On Sun, Sep 12, 2021 at 6:14 AM Salvatore Bonaccorso <carnil@debian.org> wrote:

> > > >

> > > > On Wed, Sep 01, 2021 at 01:40:26PM +0300, Dan Carpenter wrote:  

> > > > > On Mon, Aug 16, 2021 at 10:27:22AM +0300, Dan Carpenter wrote:  

> > > > > > The bounds checking in avc_ca_pmt() is not strict enough.  It should

> > > > > > be checking "read_pos + 4" because it's reading 5 bytes.  If the

> > > > > > "es_info_length" is non-zero then it reads a 6th byte so there needs to

> > > > > > be an additional check for that.

> > > > > >

> > > > > > I also added checks for the "write_pos".  I don't think these are

> > > > > > required because "read_pos" and "write_pos" are tied together so

> > > > > > checking one ought to be enough.  

> > > 

> > > They may be in sync at a fixed offset, but the buffer length of the

> > > read ("int length") is not in sync with the buffer length for the

> > > write ("sizeof(c->operand)").

> > > 

> > > So I do think the write pos limit checking is actually necessary and needed.

> > > 

> > > > > > RESEND: this patch got lost somehow.  

> > > > >

> > > > > What the heck?  Someone on patchwork just marked this patch as obsolete

> > > > > again!!!  

> > > 

> > > Can we please make sure patchwork has some logging so that that kind

> > > of thing shows _who_ did this?

> > 

> > I've been wanting a feature like that on patchwork for years. Basically,

> > when there's more then a single person capable of accessing a patchwork

> > instance, there's no way to log who changed the status, nor to control who

> > can delegate a patch to someone else or not.

> > 

> > At least for me, touching patchwork is very hard, as the the entire login

> > logic, as well as the database model itself, is abstracted by Django. So,

> > I can't simply change a SQL insert clause there to add something else to

> > their logs nor to change the sent email that it is pushed when a patch

> > status changed.

> > 

> > I ended adding an internal log to indicate when I do some changes on my

> > patchwork instance via script a couple of years ago.

> > 

> > > > Someone knows what is going on here, i.e. what is the problem?  

> > > 

> > > Dan, can you just send that fix to me directly, with the fixed commit

> > > message (see above), and we can close this.

> > 

> > Feel free to add my:

> > 

> > 	Acked-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

> 

> I'm sorry for prodding again, I guess I'm becoming a bit annoying :-/

> 

> Dan, could you sent the patch with the above to Linus directly so it

> can show up in at least 5.15-rc3? I guess it's now to late for

> 5.15-rc2.


It looks this is still not yet applied up to 5.15-rc5, if I'm not
mistaken.

Regards,
Salvatore
diff mbox series

Patch

diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c
index 2bf9467b917d..71991f8638e6 100644
--- a/drivers/media/firewire/firedtv-avc.c
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -1165,7 +1165,11 @@  int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
 		read_pos += program_info_length;
 		write_pos += program_info_length;
 	}
-	while (read_pos < length) {
+	while (read_pos + 4 < length) {
+		if (write_pos + 4 >= sizeof(c->operand) - 4) {
+			ret = -EINVAL;
+			goto out;
+		}
 		c->operand[write_pos++] = msg[read_pos++];
 		c->operand[write_pos++] = msg[read_pos++];
 		c->operand[write_pos++] = msg[read_pos++];
@@ -1177,13 +1181,17 @@  int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
 		c->operand[write_pos++] = es_info_length >> 8;
 		c->operand[write_pos++] = es_info_length & 0xff;
 		if (es_info_length > 0) {
+			if (read_pos >= length) {
+				ret = -EINVAL;
+				goto out;
+			}
 			pmt_cmd_id = msg[read_pos++];
 			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
 				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
 					pmt_cmd_id);
 
-			if (es_info_length > sizeof(c->operand) - 4 -
-					     write_pos) {
+			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||
+			    es_info_length > length - read_pos) {
 				ret = -EINVAL;
 				goto out;
 			}
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c
index 9363d005e2b6..2d6992ac5dd6 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -134,6 +134,8 @@  static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
 	} else {
 		data_length = msg->msg[3];
 	}
+	if (data_length > sizeof(msg->msg) - 4)
+		return -EINVAL;
 
 	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }