diff mbox series

[net-next,1/3] bnxt_en: check for fw_ver_str truncation

Message ID 20240705-bnxt-str-v1-1-bafc769ed89e@kernel.org (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series bnxt_en: address string truncation | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 816 this patch: 816
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 5 of 5 maintainers
netdev/build_clang success Errors and warnings before: 821 this patch: 821
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 822 this patch: 821
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 41 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-07-05--15-00 (tests: 694)

Commit Message

Simon Horman July 5, 2024, 11:26 a.m. UTC
Given the sizes of the buffers involved, it is theoretically
possible for fw_ver_str to be truncated. Detect this and
stop ethtool initialisation if this occurs.

Flagged by gcc-14:

  .../bnxt_ethtool.c: In function 'bnxt_ethtool_init':
  drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c:4144:32: warning: '%s' directive output may be truncated writing up to 31 bytes into a region of size 26 [-Wformat-truncation=]
   4144 |                          "/pkg %s", buf);
        |                                ^~   ~~~
  In function 'bnxt_get_pkgver',
      inlined from 'bnxt_ethtool_init' at .../bnxt_ethtool.c:5056:3:
  .../bnxt_ethtool.c:4143:17: note: 'snprintf' output between 6 and 37 bytes into a destination of size 31
   4143 |                 snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
        |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   4144 |                          "/pkg %s", buf);
        |                          ~~~~~~~~~~~~~~~

Compile tested only.

Signed-off-by: Simon Horman <horms@kernel.org>
---
It appears to me that size is underestimated by 1 byte -
it should be FW_VER_STR_LEN - offset rather than FW_VER_STR_LEN - offset - 1,
because the size argument to snprintf should include the space for the
trailing '\0'. But I have not changed that as it is separate from
the issue this patch addresses.
---
 drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

Comments

Przemek Kitszel July 5, 2024, 12:37 p.m. UTC | #1
On 7/5/24 13:26, Simon Horman wrote:
> Given the sizes of the buffers involved, it is theoretically
> possible for fw_ver_str to be truncated. Detect this and
> stop ethtool initialisation if this occurs.
> 
> Flagged by gcc-14:
> 
>    .../bnxt_ethtool.c: In function 'bnxt_ethtool_init':
>    drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c:4144:32: warning: '%s' directive output may be truncated writing up to 31 bytes into a region of size 26 [-Wformat-truncation=]
>     4144 |                          "/pkg %s", buf);
>          |                                ^~   ~~~

gcc is right, and you are right that we don't want such warnings
but I believe that the current flow is fine (copy as much as possible,
then proceed)

>    In function 'bnxt_get_pkgver',
>        inlined from 'bnxt_ethtool_init' at .../bnxt_ethtool.c:5056:3:
>    .../bnxt_ethtool.c:4143:17: note: 'snprintf' output between 6 and 37 bytes into a destination of size 31
>     4143 |                 snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
>          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     4144 |                          "/pkg %s", buf);
>          |                          ~~~~~~~~~~~~~~~
> 
> Compile tested only.
> 
> Signed-off-by: Simon Horman <horms@kernel.org>
> ---
> It appears to me that size is underestimated by 1 byte -
> it should be FW_VER_STR_LEN - offset rather than FW_VER_STR_LEN - offset - 1,
> because the size argument to snprintf should include the space for the
> trailing '\0'. But I have not changed that as it is separate from
> the issue this patch addresses.

you are addressing "bad size" for copying strings around, I will just
fix that part too

> ---
>   drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 23 ++++++++++++++++-------
>   1 file changed, 16 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> index bf157f6cc042..5ccc3cc4ba7d 100644
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> @@ -4132,17 +4132,23 @@ int bnxt_get_pkginfo(struct net_device *dev, char *ver, int size)
>   	return rc;
>   }
>   
> -static void bnxt_get_pkgver(struct net_device *dev)
> +static int bnxt_get_pkgver(struct net_device *dev)
>   {
>   	struct bnxt *bp = netdev_priv(dev);
>   	char buf[FW_VER_STR_LEN];
> -	int len;
>   
>   	if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) {
> -		len = strlen(bp->fw_ver_str);
> -		snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
> -			 "/pkg %s", buf);
> +		int offset, size, rc;
> +
> +		offset = strlen(bp->fw_ver_str);
> +		size = FW_VER_STR_LEN - offset - 1;
> +
> +		rc = snprintf(bp->fw_ver_str + offset, size, "/pkg %s", buf);
> +		if (rc >= size)
> +			return -E2BIG;

On error I would just replace last few bytes with "(...)" or "...", or
even "~". Other option is to enlarge bp->fw_ver_str, but I have not
looked there.

>   	}
> +
> +	return 0;
>   }
>   
>   static int bnxt_get_eeprom(struct net_device *dev,
> @@ -5052,8 +5058,11 @@ void bnxt_ethtool_init(struct bnxt *bp)
>   	struct net_device *dev = bp->dev;
>   	int i, rc;
>   
> -	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER))
> -		bnxt_get_pkgver(dev);
> +	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER)) {
> +		rc = bnxt_get_pkgver(dev);
> +		if (rc)
> +			return;

and here you are changing the flow, I would like to still init the
rest of the bnxt' ethtool stuff despite one informative string
being turncated

> +	}
>   
>   	bp->num_tests = 0;
>   	if (bp->hwrm_spec_code < 0x10704 || !BNXT_PF(bp))
>
Simon Horman July 5, 2024, 4:06 p.m. UTC | #2
On Fri, Jul 05, 2024 at 02:37:58PM +0200, Przemek Kitszel wrote:
> On 7/5/24 13:26, Simon Horman wrote:
> > Given the sizes of the buffers involved, it is theoretically
> > possible for fw_ver_str to be truncated. Detect this and
> > stop ethtool initialisation if this occurs.
> > 
> > Flagged by gcc-14:
> > 
> >    .../bnxt_ethtool.c: In function 'bnxt_ethtool_init':
> >    drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c:4144:32: warning: '%s' directive output may be truncated writing up to 31 bytes into a region of size 26 [-Wformat-truncation=]
> >     4144 |                          "/pkg %s", buf);
> >          |                                ^~   ~~~
> 
> gcc is right, and you are right that we don't want such warnings
> but I believe that the current flow is fine (copy as much as possible,
> then proceed)
> 
> >    In function 'bnxt_get_pkgver',
> >        inlined from 'bnxt_ethtool_init' at .../bnxt_ethtool.c:5056:3:
> >    .../bnxt_ethtool.c:4143:17: note: 'snprintf' output between 6 and 37 bytes into a destination of size 31
> >     4143 |                 snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
> >          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> >     4144 |                          "/pkg %s", buf);
> >          |                          ~~~~~~~~~~~~~~~
> > 
> > Compile tested only.
> > 
> > Signed-off-by: Simon Horman <horms@kernel.org>
> > ---
> > It appears to me that size is underestimated by 1 byte -
> > it should be FW_VER_STR_LEN - offset rather than FW_VER_STR_LEN - offset - 1,
> > because the size argument to snprintf should include the space for the
> > trailing '\0'. But I have not changed that as it is separate from
> > the issue this patch addresses.
> 
> you are addressing "bad size" for copying strings around, I will just
> fix that part too

Right, I was thinking of handling that separately.

> > ---
> >   drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 23 ++++++++++++++++-------
> >   1 file changed, 16 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > index bf157f6cc042..5ccc3cc4ba7d 100644
> > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > @@ -4132,17 +4132,23 @@ int bnxt_get_pkginfo(struct net_device *dev, char *ver, int size)
> >   	return rc;
> >   }
> > -static void bnxt_get_pkgver(struct net_device *dev)
> > +static int bnxt_get_pkgver(struct net_device *dev)
> >   {
> >   	struct bnxt *bp = netdev_priv(dev);
> >   	char buf[FW_VER_STR_LEN];
> > -	int len;
> >   	if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) {
> > -		len = strlen(bp->fw_ver_str);
> > -		snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
> > -			 "/pkg %s", buf);
> > +		int offset, size, rc;
> > +
> > +		offset = strlen(bp->fw_ver_str);
> > +		size = FW_VER_STR_LEN - offset - 1;
> > +
> > +		rc = snprintf(bp->fw_ver_str + offset, size, "/pkg %s", buf);
> > +		if (rc >= size)
> > +			return -E2BIG;
> 
> On error I would just replace last few bytes with "(...)" or "...", or
> even "~". Other option is to enlarge bp->fw_ver_str, but I have not
> looked there.
> 
> >   	}
> > +
> > +	return 0;
> >   }
> >   static int bnxt_get_eeprom(struct net_device *dev,
> > @@ -5052,8 +5058,11 @@ void bnxt_ethtool_init(struct bnxt *bp)
> >   	struct net_device *dev = bp->dev;
> >   	int i, rc;
> > -	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER))
> > -		bnxt_get_pkgver(dev);
> > +	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER)) {
> > +		rc = bnxt_get_pkgver(dev);
> > +		if (rc)
> > +			return;
> 
> and here you are changing the flow, I would like to still init the
> rest of the bnxt' ethtool stuff despite one informative string
> being turncated

Thanks, I'm fine with your suggestion.
But I'll wait to see if there is feedback from others, especially Broadcom.

> > +	}
> >   	bp->num_tests = 0;
> >   	if (bp->hwrm_spec_code < 0x10704 || !BNXT_PF(bp))
> > 
>
Pavan Chebbi July 5, 2024, 5:03 p.m. UTC | #3
On Fri, Jul 5, 2024 at 9:36 PM Simon Horman <horms@kernel.org> wrote:
>
> On Fri, Jul 05, 2024 at 02:37:58PM +0200, Przemek Kitszel wrote:
> > On 7/5/24 13:26, Simon Horman wrote:
> > > Given the sizes of the buffers involved, it is theoretically
> > > possible for fw_ver_str to be truncated. Detect this and
> > > stop ethtool initialisation if this occurs.
> > >
> > > Flagged by gcc-14:
> > >
> > >    .../bnxt_ethtool.c: In function 'bnxt_ethtool_init':
> > >    drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c:4144:32: warning: '%s' directive output may be truncated writing up to 31 bytes into a region of size 26 [-Wformat-truncation=]
> > >     4144 |                          "/pkg %s", buf);
> > >          |                                ^~   ~~~
> >
> > gcc is right, and you are right that we don't want such warnings
> > but I believe that the current flow is fine (copy as much as possible,
> > then proceed)
> >
> > >    In function 'bnxt_get_pkgver',
> > >        inlined from 'bnxt_ethtool_init' at .../bnxt_ethtool.c:5056:3:
> > >    .../bnxt_ethtool.c:4143:17: note: 'snprintf' output between 6 and 37 bytes into a destination of size 31
> > >     4143 |                 snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
> > >          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >     4144 |                          "/pkg %s", buf);
> > >          |                          ~~~~~~~~~~~~~~~
> > >
> > > Compile tested only.
> > >
> > > Signed-off-by: Simon Horman <horms@kernel.org>
> > > ---
> > > It appears to me that size is underestimated by 1 byte -
> > > it should be FW_VER_STR_LEN - offset rather than FW_VER_STR_LEN - offset - 1,
> > > because the size argument to snprintf should include the space for the
> > > trailing '\0'. But I have not changed that as it is separate from
> > > the issue this patch addresses.
> >
> > you are addressing "bad size" for copying strings around, I will just
> > fix that part too
>
> Right, I was thinking of handling that separately.
>
> > > ---
> > >   drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 23 ++++++++++++++++-------
> > >   1 file changed, 16 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > > index bf157f6cc042..5ccc3cc4ba7d 100644
> > > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> > > @@ -4132,17 +4132,23 @@ int bnxt_get_pkginfo(struct net_device *dev, char *ver, int size)
> > >     return rc;
> > >   }
> > > -static void bnxt_get_pkgver(struct net_device *dev)
> > > +static int bnxt_get_pkgver(struct net_device *dev)
> > >   {
> > >     struct bnxt *bp = netdev_priv(dev);
> > >     char buf[FW_VER_STR_LEN];
> > > -   int len;
> > >     if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) {
> > > -           len = strlen(bp->fw_ver_str);
> > > -           snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
> > > -                    "/pkg %s", buf);
> > > +           int offset, size, rc;
> > > +
> > > +           offset = strlen(bp->fw_ver_str);
> > > +           size = FW_VER_STR_LEN - offset - 1;
> > > +
> > > +           rc = snprintf(bp->fw_ver_str + offset, size, "/pkg %s", buf);
> > > +           if (rc >= size)
> > > +                   return -E2BIG;
> >
> > On error I would just replace last few bytes with "(...)" or "...", or
> > even "~". Other option is to enlarge bp->fw_ver_str, but I have not
> > looked there.
> >
> > >     }
> > > +
> > > +   return 0;
> > >   }
> > >   static int bnxt_get_eeprom(struct net_device *dev,
> > > @@ -5052,8 +5058,11 @@ void bnxt_ethtool_init(struct bnxt *bp)
> > >     struct net_device *dev = bp->dev;
> > >     int i, rc;
> > > -   if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER))
> > > -           bnxt_get_pkgver(dev);
> > > +   if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER)) {
> > > +           rc = bnxt_get_pkgver(dev);
> > > +           if (rc)
> > > +                   return;
> >
> > and here you are changing the flow, I would like to still init the
> > rest of the bnxt' ethtool stuff despite one informative string
> > being turncated
>
> Thanks, I'm fine with your suggestion.
> But I'll wait to see if there is feedback from others, especially Broadcom.

Hi Simon, thanks for the patch. I'd agree with Przemek. Would
definitely like to have the init complete just as before.

>
> > > +   }
> > >     bp->num_tests = 0;
> > >     if (bp->hwrm_spec_code < 0x10704 || !BNXT_PF(bp))
> > >
> >
>
Michael Chan July 5, 2024, 5:39 p.m. UTC | #4
On Fri, Jul 5, 2024 at 10:03 AM Pavan Chebbi <pavan.chebbi@broadcom.com> wrote:
>
> On Fri, Jul 5, 2024 at 9:36 PM Simon Horman <horms@kernel.org> wrote:
> >
> > On Fri, Jul 05, 2024 at 02:37:58PM +0200, Przemek Kitszel wrote:
> > > On 7/5/24 13:26, Simon Horman wrote:
> > > > It appears to me that size is underestimated by 1 byte -
> > > > it should be FW_VER_STR_LEN - offset rather than FW_VER_STR_LEN - offset - 1,
> > > > because the size argument to snprintf should include the space for the
> > > > trailing '\0'. But I have not changed that as it is separate from
> > > > the issue this patch addresses.
> > >
> > > you are addressing "bad size" for copying strings around, I will just
> > > fix that part too
> >
> > Right, I was thinking of handling that separately.

Yes, please fix the size as well.

> > > >   static int bnxt_get_eeprom(struct net_device *dev,
> > > > @@ -5052,8 +5058,11 @@ void bnxt_ethtool_init(struct bnxt *bp)
> > > >     struct net_device *dev = bp->dev;
> > > >     int i, rc;
> > > > -   if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER))
> > > > -           bnxt_get_pkgver(dev);
> > > > +   if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER)) {
> > > > +           rc = bnxt_get_pkgver(dev);
> > > > +           if (rc)
> > > > +                   return;
> > >
> > > and here you are changing the flow, I would like to still init the
> > > rest of the bnxt' ethtool stuff despite one informative string
> > > being turncated
> >
> > Thanks, I'm fine with your suggestion.
> > But I'll wait to see if there is feedback from others, especially Broadcom.
>
> Hi Simon, thanks for the patch. I'd agree with Przemek. Would
> definitely like to have the init complete just as before.
>

I agree as well.  We should continue with the rest of
bnxt_ethtool_init().  Thanks for the patch.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index bf157f6cc042..5ccc3cc4ba7d 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -4132,17 +4132,23 @@  int bnxt_get_pkginfo(struct net_device *dev, char *ver, int size)
 	return rc;
 }
 
-static void bnxt_get_pkgver(struct net_device *dev)
+static int bnxt_get_pkgver(struct net_device *dev)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	char buf[FW_VER_STR_LEN];
-	int len;
 
 	if (!bnxt_get_pkginfo(dev, buf, sizeof(buf))) {
-		len = strlen(bp->fw_ver_str);
-		snprintf(bp->fw_ver_str + len, FW_VER_STR_LEN - len - 1,
-			 "/pkg %s", buf);
+		int offset, size, rc;
+
+		offset = strlen(bp->fw_ver_str);
+		size = FW_VER_STR_LEN - offset - 1;
+
+		rc = snprintf(bp->fw_ver_str + offset, size, "/pkg %s", buf);
+		if (rc >= size)
+			return -E2BIG;
 	}
+
+	return 0;
 }
 
 static int bnxt_get_eeprom(struct net_device *dev,
@@ -5052,8 +5058,11 @@  void bnxt_ethtool_init(struct bnxt *bp)
 	struct net_device *dev = bp->dev;
 	int i, rc;
 
-	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER))
-		bnxt_get_pkgver(dev);
+	if (!(bp->fw_cap & BNXT_FW_CAP_PKG_VER)) {
+		rc = bnxt_get_pkgver(dev);
+		if (rc)
+			return;
+	}
 
 	bp->num_tests = 0;
 	if (bp->hwrm_spec_code < 0x10704 || !BNXT_PF(bp))