All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
       [not found] <000001d73031$d5304480$7f90cd80$@nsfocus.com>
@ 2021-04-14  8:57 ` Dan Carpenter
  2021-04-19 21:42   ` Kees Cook
                     ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Dan Carpenter @ 2021-04-14  8:57 UTC (permalink / raw)
  To: Stefan Richter, Luo Likang
  Cc: security, linux-distros, Mauro Carvalho Chehab, linux-media,
	linux1394-devel

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


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-04-14  8:57 ` [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() Dan Carpenter
@ 2021-04-19 21:42   ` Kees Cook
  2021-06-07 15:23   ` [PATCH v2] " Dan Carpenter
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Kees Cook @ 2021-04-19 21:42 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Stefan Richter, Luo Likang, security, linux-distros,
	Mauro Carvalho Chehab, linux-media, linux1394-devel

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-04-14  8:57 ` [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() Dan Carpenter
  2021-04-19 21:42   ` Kees Cook
@ 2021-06-07 15:23   ` Dan Carpenter
  2021-07-16  9:28     ` Petr Mladek
  2021-07-19 10:25   ` [PATCH] " Dan Carpenter
  2021-07-29 10:32   ` Greg KH
  3 siblings, 1 reply; 20+ messages in thread
From: Dan Carpenter @ 2021-06-07 15:23 UTC (permalink / raw)
  To: Stefan Richter, Luo Likang
  Cc: Mauro Carvalho Chehab, linux-media, linux1394-devel, Yang Yanchao

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().

Cc: stable@vger.kernel.org
Reported-by: Luo Likang <luolikang@nsfocus.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
v2: Change the limit in fdtv_ca_pmt() from "sizeof(msg->msg) - 4" to
"sizeof(msg->msg) - data_pos".

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) - data_pos)
+		return -EINVAL;
 
 	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }
-- 
2.30.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-06-07 15:23   ` [PATCH v2] " Dan Carpenter
@ 2021-07-16  9:28     ` Petr Mladek
  0 siblings, 0 replies; 20+ messages in thread
From: Petr Mladek @ 2021-07-16  9:28 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Stefan Richter, Luo Likang, Mauro Carvalho Chehab, linux-media,
	linux1394-devel, Yang Yanchao

On Mon 2021-06-07 18:23:48, 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().
> 
> Cc: stable@vger.kernel.org
> Reported-by: Luo Likang <luolikang@nsfocus.com>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

I do not see this fix in 5.14-rc1. Has it been solved another
way in the end, please?

Best Regards,
Petr

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-04-14  8:57 ` [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() Dan Carpenter
  2021-04-19 21:42   ` Kees Cook
  2021-06-07 15:23   ` [PATCH v2] " Dan Carpenter
@ 2021-07-19 10:25   ` Dan Carpenter
  2021-07-29 10:32   ` Greg KH
  3 siblings, 0 replies; 20+ messages in thread
From: Dan Carpenter @ 2021-07-19 10:25 UTC (permalink / raw)
  To: Stefan Richter, Luo Likang
  Cc: Mauro Carvalho Chehab, linux-media, linux1394-devel

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-04-14  8:57 ` [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() Dan Carpenter
                     ` (2 preceding siblings ...)
  2021-07-19 10:25   ` [PATCH] " Dan Carpenter
@ 2021-07-29 10:32   ` Greg KH
  2021-08-16  7:01     ` Salvatore Bonaccorso
  3 siblings, 1 reply; 20+ messages in thread
From: Greg KH @ 2021-07-29 10:32 UTC (permalink / raw)
  To: Dan Carpenter, Stefan Richter, Luo Likang, security,
	linux-distros, Mauro Carvalho Chehab, linux-media,
	linux1394-devel

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-07-29 10:32   ` Greg KH
@ 2021-08-16  7:01     ` Salvatore Bonaccorso
  2021-08-16  7:27       ` [PATCH v2 RESEND] " Dan Carpenter
  0 siblings, 1 reply; 20+ messages in thread
From: Salvatore Bonaccorso @ 2021-08-16  7:01 UTC (permalink / raw)
  To: Greg KH
  Cc: Dan Carpenter, Stefan Richter, Luo Likang, security,
	linux-distros, Mauro Carvalho Chehab, linux-media,
	linux1394-devel

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-08-16  7:01     ` Salvatore Bonaccorso
@ 2021-08-16  7:27       ` Dan Carpenter
  2021-09-01 10:40         ` Dan Carpenter
  0 siblings, 1 reply; 20+ messages in thread
From: Dan Carpenter @ 2021-08-16  7:27 UTC (permalink / raw)
  To: Stefan Richter, Luo Likang
  Cc: Mauro Carvalho Chehab, linux-media, linux1394-devel,
	Yang Yanchao, Salvatore Bonaccorso, security, linux-distros

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.

v2: Change the limit in fdtv_ca_pmt() from "sizeof(msg->msg) - 4" to
"sizeof(msg->msg) - data_pos".

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) - data_pos)
+		return -EINVAL;
 
 	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-08-16  7:27       ` [PATCH v2 RESEND] " Dan Carpenter
@ 2021-09-01 10:40         ` Dan Carpenter
  2021-09-12 13:14           ` Salvatore Bonaccorso
  0 siblings, 1 reply; 20+ messages in thread
From: Dan Carpenter @ 2021-09-01 10:40 UTC (permalink / raw)
  To: Stefan Richter, Luo Likang, Mauro Carvalho Chehab
  Cc: linux-media, linux1394-devel, Yang Yanchao, Salvatore Bonaccorso,
	security, linux-distros

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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-01 10:40         ` Dan Carpenter
@ 2021-09-12 13:14           ` Salvatore Bonaccorso
  2021-09-12 18:26             ` Linus Torvalds
  0 siblings, 1 reply; 20+ messages in thread
From: Salvatore Bonaccorso @ 2021-09-12 13:14 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Stefan Richter, Luo Likang, Mauro Carvalho Chehab, linux-media,
	linux1394-devel, Yang Yanchao, security, linux-distros

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-12 13:14           ` Salvatore Bonaccorso
@ 2021-09-12 18:26             ` Linus Torvalds
  2021-09-13  2:50               ` Michael Ellerman
  2021-09-13 13:23               ` Mauro Carvalho Chehab
  0 siblings, 2 replies; 20+ messages in thread
From: Linus Torvalds @ 2021-09-12 18:26 UTC (permalink / raw)
  To: Salvatore Bonaccorso
  Cc: Dan Carpenter, Stefan Richter, Luo Likang, Mauro Carvalho Chehab,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers, linux-distros

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-12 18:26             ` Linus Torvalds
@ 2021-09-13  2:50               ` Michael Ellerman
  2021-09-13 13:23               ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 20+ messages in thread
From: Michael Ellerman @ 2021-09-13  2:50 UTC (permalink / raw)
  To: Linus Torvalds, Salvatore Bonaccorso
  Cc: Dan Carpenter, Stefan Richter, Luo Likang, Mauro Carvalho Chehab,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-12 18:26             ` Linus Torvalds
  2021-09-13  2:50               ` Michael Ellerman
@ 2021-09-13 13:23               ` Mauro Carvalho Chehab
  2021-09-19 18:45                 ` Salvatore Bonaccorso
  1 sibling, 1 reply; 20+ messages in thread
From: Mauro Carvalho Chehab @ 2021-09-13 13:23 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Salvatore Bonaccorso, Dan Carpenter, Stefan Richter, Luo Likang,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers, linux-distros

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-13 13:23               ` Mauro Carvalho Chehab
@ 2021-09-19 18:45                 ` Salvatore Bonaccorso
  2021-10-11  7:04                   ` Salvatore Bonaccorso
  0 siblings, 1 reply; 20+ messages in thread
From: Salvatore Bonaccorso @ 2021-09-19 18:45 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Dan Carpenter
  Cc: Linus Torvalds, Stefan Richter, Luo Likang,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 RESEND] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-09-19 18:45                 ` Salvatore Bonaccorso
@ 2021-10-11  7:04                   ` Salvatore Bonaccorso
  2021-10-11  9:42                     ` [PATCH] " Dan Carpenter
  0 siblings, 1 reply; 20+ messages in thread
From: Salvatore Bonaccorso @ 2021-10-11  7:04 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Dan Carpenter, Linus Torvalds, Stefan Richter, Luo Likang,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers

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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
  2021-10-11  7:04                   ` Salvatore Bonaccorso
@ 2021-10-11  9:42                     ` Dan Carpenter
  0 siblings, 0 replies; 20+ messages in thread
From: Dan Carpenter @ 2021-10-11  9:42 UTC (permalink / raw)
  To: Salvatore Bonaccorso, Mauro Carvalho Chehab, Hans Verkuil
  Cc: Linus Torvalds, Stefan Richter, Luo Likang,
	Linux Media Mailing List, linux1394-devel, Yang Yanchao,
	Security Officers

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().

Cc: stable@vger.kernel.org
Reported-by: Luo Likang <luolikang@nsfocus.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---

Cherry picked from linux-next.

 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..e0d57e09dab0 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) - data_pos)
+		return -EINVAL;
 
 	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH] media firewire firedtv-avc fix a buffer overflow in avc_ca_pmt()
  2021-06-07  7:39 Yang Yanchao
  2021-06-07  9:26 ` Greg KH
@ 2021-06-07 14:28 ` Dan Carpenter
  1 sibling, 0 replies; 20+ messages in thread
From: Dan Carpenter @ 2021-06-07 14:28 UTC (permalink / raw)
  To: Yang Yanchao
  Cc: linux-distros, linux-media, linux1394-devel, mchehab, security

Thanks for resending this patch, but you need to preserve the author
and Reported-by tags.

https://lore.kernel.org/linux-media/YHaulytonFcW+lyZ@mwanda/

You changed the check in fdtv_ca_pmt() but I don't understand why you
did that...  But looking at it again, I think neither of us was correct,
instead of "sizeof(msg->msg) - 4" it should be "- data_pos":

	if (data_length > sizeof(msg->msg) - data_pos)
		return -EINVAL;

I will resend a v2.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] media firewire firedtv-avc fix a buffer overflow in avc_ca_pmt()
  2021-06-07  7:39 Yang Yanchao
@ 2021-06-07  9:26 ` Greg KH
  2021-06-07 14:28 ` Dan Carpenter
  1 sibling, 0 replies; 20+ messages in thread
From: Greg KH @ 2021-06-07  9:26 UTC (permalink / raw)
  To: Yang Yanchao
  Cc: dan.carpenter, linux-distros, linux-media, linux1394-devel,
	mchehab, security

On Mon, Jun 07, 2021 at 03:39:00PM +0800, Yang Yanchao wrote:
> For CVE-2021-3542:

What does that mean?  We don't know what cve numbers refer to as there
is no way to really track and update the information with them.  Please
spell out the issue please.

> 
> 1???read_pos will be added four times in the patch, 
> so use "read_pos + 4 < length" and write_pos as well

what is "???" here?

> 
> 2. The last four bits of c->operand are used for CRC, 
> so "sizeof (C - > operand) - 4" is used
> 
> 3. "read_pos+=2" is added after the end of read_pos, so add value (read_pos >= length)
> 
> 4. In order to avoid memcpy crossing the boundary, es_ info_ length > length - read_ pos
> 
> 5. When the date_length is a specific input of a construction,it will cause memcpy
>  to exceed the boundary, "(MSG - > MSG [3] & 0x7F) + date_ length) > (sizeof(msg->msg) - 4)"

I do not understand, this is saying what you did, not _why_ you did it.
can you please rework this to make it more obvious what you are doing?

And shouldn't this be more than one patch?  A series of patches, each
fixing one thing?

And no need to put security@kernel.org on this now that you have sent it
to a public mailing list.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH] media firewire firedtv-avc fix a buffer overflow in avc_ca_pmt()
@ 2021-06-07  7:39 Yang Yanchao
  2021-06-07  9:26 ` Greg KH
  2021-06-07 14:28 ` Dan Carpenter
  0 siblings, 2 replies; 20+ messages in thread
From: Yang Yanchao @ 2021-06-07  7:39 UTC (permalink / raw)
  To: dan.carpenter
  Cc: linux-distros, linux-media, linux1394-devel, mchehab, security

For CVE-2021-3542:

1、read_pos will be added four times in the patch, 
so use "read_pos + 4 < length" and write_pos as well

2. The last four bits of c->operand are used for CRC, 
so "sizeof (C - > operand) - 4" is used

3. "read_pos+=2" is added after the end of read_pos, so add value (read_pos >= length)

4. In order to avoid memcpy crossing the boundary, es_ info_ length > length - read_ pos

5. When the date_length is a specific input of a construction,it will cause memcpy
 to exceed the boundary, "(MSG - > MSG [3] & 0x7F) + date_ length) > (sizeof(msg->msg) - 4)"

Signed-off-by: yangyanchao <yangyanchao6@huawei.com>
---
 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 3ef5df164..8c31cf90c 100644
--- a/drivers/media/firewire/firedtv-avc.c
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -1169,7 +1169,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++];
@@ -1181,13 +1185,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 8dc5a7495..0e7ffa156 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -135,6 +135,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
 		data_length = 0;
 		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
 			data_length = (data_length << 8) + msg->msg[data_pos++];
+		if (((msg->msg[3] & 0x7f) + date_length) > (sizeof(msg->msg) - 4))
+			return -EINVAL;
 	} else {
 		data_length = msg->msg[3];
 	}
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH] media firewire firedtv-avc fix a buffer overflow in avc_ca_pmt()
@ 2021-06-07  7:38 Yang Yanchao
  0 siblings, 0 replies; 20+ messages in thread
From: Yang Yanchao @ 2021-06-07  7:38 UTC (permalink / raw)
  To: dan.carpenter
  Cc: linux-distros, linux-media, linux1394-devel, mchehab, security

For CVE-2021-3542:

1、read_pos will be added four times in the patch, 
so use "read_pos + 4 < length" and write_pos as well

2. The last four bits of c->operand are used for CRC, 
so "sizeof (C - > operand) - 4" is used

3. "read_pos+=2" is added after the end of read_pos, so add value (read_pos >= length)

4. In order to avoid memcpy crossing the boundary, es_ info_ length > length - read_ pos

5. When the date_length is a specific input of a construction,it will cause memcpy
 to exceed the boundary, "(MSG - > MSG [3] & 0x7F) + date_ length) > (sizeof(msg->msg) - 4)"

Signed-off-by: yangyanchao <yangyanchao6@huawei.com>
---
 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 3ef5df164..8c31cf90c 100644
--- a/drivers/media/firewire/firedtv-avc.c
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -1169,7 +1169,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++];
@@ -1181,13 +1185,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 8dc5a7495..0e7ffa156 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -135,6 +135,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
 		data_length = 0;
 		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
 			data_length = (data_length << 8) + msg->msg[data_pos++];
+		if (((msg->msg[3] & 0x7f) + date_length) > (sizeof(msg->msg) - 4))
+			return -EINVAL;
 	} else {
 		data_length = msg->msg[3];
 	}
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2021-10-11  9:43 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <000001d73031$d5304480$7f90cd80$@nsfocus.com>
2021-04-14  8:57 ` [PATCH] media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt() Dan Carpenter
2021-04-19 21:42   ` Kees Cook
2021-06-07 15:23   ` [PATCH v2] " Dan Carpenter
2021-07-16  9:28     ` Petr Mladek
2021-07-19 10:25   ` [PATCH] " Dan Carpenter
2021-07-29 10:32   ` Greg KH
2021-08-16  7:01     ` Salvatore Bonaccorso
2021-08-16  7:27       ` [PATCH v2 RESEND] " Dan Carpenter
2021-09-01 10:40         ` Dan Carpenter
2021-09-12 13:14           ` Salvatore Bonaccorso
2021-09-12 18:26             ` Linus Torvalds
2021-09-13  2:50               ` Michael Ellerman
2021-09-13 13:23               ` Mauro Carvalho Chehab
2021-09-19 18:45                 ` Salvatore Bonaccorso
2021-10-11  7:04                   ` Salvatore Bonaccorso
2021-10-11  9:42                     ` [PATCH] " Dan Carpenter
2021-06-07  7:38 [PATCH] media firewire firedtv-avc " Yang Yanchao
2021-06-07  7:39 Yang Yanchao
2021-06-07  9:26 ` Greg KH
2021-06-07 14:28 ` Dan Carpenter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.