diff mbox series

drivers:atlx: Prevent integer overflow in statistics aggregation

Message ID 20241007092936.53445-1-rand.sec96@gmail.com (mailing list archive)
State Rejected
Delegated to: Netdev Maintainers
Headers show
Series drivers:atlx: Prevent integer overflow in statistics aggregation | expand

Checks

Context Check Description
netdev/series_format warning Single patches do not need cover letters; Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be 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: 6 this patch: 6
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 6 of 6 maintainers
netdev/build_clang success Errors and warnings before: 6 this patch: 6
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: 29 this patch: 29
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 42 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 9 this patch: 9
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-10-08--00-00 (tests: 773)

Commit Message

Rand Deeb Oct. 7, 2024, 9:29 a.m. UTC
The `atl1_inc_smb` function aggregates various RX and TX error counters
from the `stats_msg_block` structure. Currently, the arithmetic operations
are performed using `u32` types, which can lead to integer overflow when
summing large values. This overflow occurs before the result is cast to
a `u64`, potentially resulting in inaccurate network statistics.

To mitigate this risk, each operand in the summation is explicitly cast to
`u64` before performing the addition. This ensures that the arithmetic is
executed in 64-bit space, preventing overflow and maintaining accurate
statistics regardless of the system architecture.

Additionally, the aggregation of collision counters is also subject to
integer overflow. The operands in the summation for `collisions` are now
cast to `u64` to prevent overflow in this aggregation as well.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Signed-off-by: Rand Deeb <rand.sec96@gmail.com>
---
 drivers/net/ethernet/atheros/atlx/atl1.c | 30 ++++++++++++------------
 1 file changed, 15 insertions(+), 15 deletions(-)

Comments

Jakub Kicinski Oct. 8, 2024, 12:27 a.m. UTC | #1
On Mon,  7 Oct 2024 12:29:36 +0300 Rand Deeb wrote:
> The `atl1_inc_smb` function aggregates various RX and TX error counters
> from the `stats_msg_block` structure. Currently, the arithmetic operations
> are performed using `u32` types, which can lead to integer overflow when
> summing large values. This overflow occurs before the result is cast to
> a `u64`, potentially resulting in inaccurate network statistics.
> 
> To mitigate this risk, each operand in the summation is explicitly cast to
> `u64` before performing the addition. This ensures that the arithmetic is
> executed in 64-bit space, preventing overflow and maintaining accurate
> statistics regardless of the system architecture.

Thanks for the nice commit message, but honestly I don't think
the error counters can overflow u32 on an ancient NIC like this.
Rand Deeb Oct. 8, 2024, 4:59 p.m. UTC | #2
On Tue, Oct 8, 2024 at 3:27 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Mon,  7 Oct 2024 12:29:36 +0300 Rand Deeb wrote:
> > The `atl1_inc_smb` function aggregates various RX and TX error counters
> > from the `stats_msg_block` structure. Currently, the arithmetic operations
> > are performed using `u32` types, which can lead to integer overflow when
> > summing large values. This overflow occurs before the result is cast to
> > a `u64`, potentially resulting in inaccurate network statistics.
> >
> > To mitigate this risk, each operand in the summation is explicitly cast to
> > `u64` before performing the addition. This ensures that the arithmetic is
> > executed in 64-bit space, preventing overflow and maintaining accurate
> > statistics regardless of the system architecture.
>
> Thanks for the nice commit message, but honestly I don't think
> the error counters can overflow u32 on an ancient NIC like this.

Hi Jakub,

Thanks for your feedback, much appreciated!

Honestly, when I was investigating this, I had the same thoughts regarding
the possibility of the counters overflowing. However, I want to clarify
that the variables where we store the results of these summations (like
new_rx_errors, new_tx_errors, etc.) are already u64 types. Given that, it
seems logical to cast the operands to u64 before the addition to ensure
consistency and avoid any potential issues during the summation.

Additionally, all counters in the atl1_sft_stats structure are also
defined as u64, which reinforces the rationale for casting the operands in
the summation as well.

Thanks again for your input!

Best regards,
Rand Deeb
Jacob Keller Oct. 8, 2024, 5:13 p.m. UTC | #3
> -----Original Message-----
> From: Rand Deeb <rand.sec96@gmail.com>
> Sent: Tuesday, October 8, 2024 9:59 AM
> To: Jakub Kicinski <kuba@kernel.org>
> Cc: Chris Snook <chris.snook@gmail.com>; David S . Miller
> <davem@davemloft.net>; Eric Dumazet <edumazet@google.com>; Paolo Abeni
> <pabeni@redhat.com>; Christian Marangi <ansuelsmth@gmail.com>;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; deeb.rand@confident.ru;
> lvc-project@linuxtesting.org; voskresenski.stanislav@confident.ru
> Subject: Re: [PATCH] drivers:atlx: Prevent integer overflow in statistics aggregation
> 
> On Tue, Oct 8, 2024 at 3:27 AM Jakub Kicinski <kuba@kernel.org> wrote:
> >
> > On Mon,  7 Oct 2024 12:29:36 +0300 Rand Deeb wrote:
> > > The `atl1_inc_smb` function aggregates various RX and TX error counters
> > > from the `stats_msg_block` structure. Currently, the arithmetic operations
> > > are performed using `u32` types, which can lead to integer overflow when
> > > summing large values. This overflow occurs before the result is cast to
> > > a `u64`, potentially resulting in inaccurate network statistics.
> > >
> > > To mitigate this risk, each operand in the summation is explicitly cast to
> > > `u64` before performing the addition. This ensures that the arithmetic is
> > > executed in 64-bit space, preventing overflow and maintaining accurate
> > > statistics regardless of the system architecture.
> >
> > Thanks for the nice commit message, but honestly I don't think
> > the error counters can overflow u32 on an ancient NIC like this.
> 

2^32-1 = 4294967295

If we assume that the card operates for at least 10 years, you will need an error rate of ~14 per second to overflow a 32bit counter over the 10 year period. Longer operation uptime time could decrease the error rate. That does seem unlikely.

> Hi Jakub,
> 
> Thanks for your feedback, much appreciated!
> 
> Honestly, when I was investigating this, I had the same thoughts regarding
> the possibility of the counters overflowing. However, I want to clarify
> that the variables where we store the results of these summations (like
> new_rx_errors, new_tx_errors, etc.) are already u64 types. Given that, it
> seems logical to cast the operands to u64 before the addition to ensure
> consistency and avoid any potential issues during the summation.
> 
> Additionally, all counters in the atl1_sft_stats structure are also
> defined as u64, which reinforces the rationale for casting the operands in
> the summation as well.
> 
> Thanks again for your input!
> 
> Best regards,
> Rand Deeb

Still, if the resulting storage is already 64bit, I think it does make sense to do the arithmetic in 64bit.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index a9014d7932db..d61f46799713 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -1656,17 +1656,17 @@  static void atl1_inc_smb(struct atl1_adapter *adapter)
 	struct net_device *netdev = adapter->netdev;
 	struct stats_msg_block *smb = adapter->smb.smb;
 
-	u64 new_rx_errors = smb->rx_frag +
-			    smb->rx_fcs_err +
-			    smb->rx_len_err +
-			    smb->rx_sz_ov +
-			    smb->rx_rxf_ov +
-			    smb->rx_rrd_ov +
-			    smb->rx_align_err;
-	u64 new_tx_errors = smb->tx_late_col +
-			    smb->tx_abort_col +
-			    smb->tx_underrun +
-			    smb->tx_trunc;
+	u64 new_rx_errors = (u64)smb->rx_frag +
+			    (u64)smb->rx_fcs_err +
+			    (u64)smb->rx_len_err +
+			    (u64)smb->rx_sz_ov +
+			    (u64)smb->rx_rxf_ov +
+			    (u64)smb->rx_rrd_ov +
+			    (u64)smb->rx_align_err;
+	u64 new_tx_errors = (u64)smb->tx_late_col +
+			    (u64)smb->tx_abort_col +
+			    (u64)smb->tx_underrun +
+			    (u64)smb->tx_trunc;
 
 	/* Fill out the OS statistics structure */
 	adapter->soft_stats.rx_packets += smb->rx_ok + new_rx_errors;
@@ -1674,10 +1674,10 @@  static void atl1_inc_smb(struct atl1_adapter *adapter)
 	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;
 	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;
 	adapter->soft_stats.multicast += smb->rx_mcast;
-	adapter->soft_stats.collisions += smb->tx_1_col +
-					  smb->tx_2_col +
-					  smb->tx_late_col +
-					  smb->tx_abort_col;
+	adapter->soft_stats.collisions += (u64)smb->tx_1_col +
+					  (u64)smb->tx_2_col +
+					  (u64)smb->tx_late_col +
+					  (u64)smb->tx_abort_col;
 
 	/* Rx Errors */
 	adapter->soft_stats.rx_errors += new_rx_errors;