diff mbox series

[net-next] net: phy: mdio-bcm-unimac: Cast denominator to unsigned long to avoid overflow

Message ID 20240312165358.7712-1-d.dulov@aladdin.ru (mailing list archive)
State Deferred
Delegated to: Netdev Maintainers
Headers show
Series [net-next] net: phy: mdio-bcm-unimac: Cast denominator to unsigned long to avoid overflow | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
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: 940 this patch: 940
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 10 of 10 maintainers
netdev/build_clang success Errors and warnings before: 956 this patch: 956
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: 956 this patch: 956
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 8 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

Commit Message

Daniil Dulov March 12, 2024, 4:53 p.m. UTC
The expression priv->clk_freq * 2 can lead to overflow that will cause
a division by zero. So, let's cast it to unsigned long to avoid it.

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

Signed-off-by: Daniil Dulov <d.dulov@aladdin.ru>
---
 drivers/net/mdio/mdio-bcm-unimac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Jakub Kicinski March 12, 2024, 5:16 p.m. UTC | #1
On Tue, 12 Mar 2024 19:53:58 +0300 Daniil Dulov wrote:
> The expression priv->clk_freq * 2 can lead to overflow that will cause
> a division by zero. So, let's cast it to unsigned long to avoid it.

## Form letter - net-next-closed

The merge window for v6.9 has begun and we have already posted our pull
request. Therefore net-next is closed for new drivers, features, code
refactoring and optimizations. We are currently accepting bug fixes only.

Please repost when net-next reopens after March 25th.

RFC patches sent for review only are obviously welcome at any time.

See: https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#development-cycle
Russell King (Oracle) March 12, 2024, 5:18 p.m. UTC | #2
On Tue, Mar 12, 2024 at 07:53:58PM +0300, Daniil Dulov wrote:
> The expression priv->clk_freq * 2 can lead to overflow that will cause
> a division by zero. So, let's cast it to unsigned long to avoid it.

How does casting this help? "unsigned long" can still be 32-bit.
Maybe unimac_mdio_probe() should be validating the value it read from
DT won't overflow? I suspect that a value of 2.1GHz is way too large
for this property in any case.

https://en.wikipedia.org/wiki/Management_Data_Input/Output#Electrical_specification

(note, this driver is clause-22 only.)
Florian Fainelli March 12, 2024, 5:23 p.m. UTC | #3
On 3/12/24 10:18, Russell King (Oracle) wrote:
> On Tue, Mar 12, 2024 at 07:53:58PM +0300, Daniil Dulov wrote:
>> The expression priv->clk_freq * 2 can lead to overflow that will cause
>> a division by zero. So, let's cast it to unsigned long to avoid it.
> 
> How does casting this help? "unsigned long" can still be 32-bit.
> Maybe unimac_mdio_probe() should be validating the value it read from
> DT won't overflow? I suspect that a value of 2.1GHz is way too large
> for this property in any case.
> 
> https://en.wikipedia.org/wiki/Management_Data_Input/Output#Electrical_specification
> 
> (note, this driver is clause-22 only.)
> 

Had commented on the previous version (not sure why this was not 
prefixed with v2) that the maximum clock frequency for this clock is 
250MHz, the driver could check that to prevent for an overflow, most 
certainly.
Doug Berger March 12, 2024, 7:23 p.m. UTC | #4
On 3/12/2024 10:23 AM, Florian Fainelli wrote:
> On 3/12/24 10:18, Russell King (Oracle) wrote:
>> On Tue, Mar 12, 2024 at 07:53:58PM +0300, Daniil Dulov wrote:
>>> The expression priv->clk_freq * 2 can lead to overflow that will cause
>>> a division by zero. So, let's cast it to unsigned long to avoid it.
>>
>> How does casting this help? "unsigned long" can still be 32-bit.
>> Maybe unimac_mdio_probe() should be validating the value it read from
>> DT won't overflow? I suspect that a value of 2.1GHz is way too large
>> for this property in any case.
>>
>> https://en.wikipedia.org/wiki/Management_Data_Input/Output#Electrical_specification
>>
>> (note, this driver is clause-22 only.)
>>
> 
> Had commented on the previous version (not sure why this was not 
> prefixed with v2) that the maximum clock frequency for this clock is 
> 250MHz, the driver could check that to prevent for an overflow, most 
> certainly.

Could also use:
-	div = (rate / (2 * priv->clk_freq)) - 1;
+	div = ((rate / priv->clk_freq) >> 1) - 1;
which is mathematically equivalent without the risk of overflow.

-Doug
Russell King (Oracle) March 12, 2024, 7:42 p.m. UTC | #5
On Tue, Mar 12, 2024 at 12:23:20PM -0700, Doug Berger wrote:
> On 3/12/2024 10:23 AM, Florian Fainelli wrote:
> > On 3/12/24 10:18, Russell King (Oracle) wrote:
> > > On Tue, Mar 12, 2024 at 07:53:58PM +0300, Daniil Dulov wrote:
> > > > The expression priv->clk_freq * 2 can lead to overflow that will cause
> > > > a division by zero. So, let's cast it to unsigned long to avoid it.
> > > 
> > > How does casting this help? "unsigned long" can still be 32-bit.
> > > Maybe unimac_mdio_probe() should be validating the value it read from
> > > DT won't overflow? I suspect that a value of 2.1GHz is way too large
> > > for this property in any case.
> > > 
> > > https://en.wikipedia.org/wiki/Management_Data_Input/Output#Electrical_specification
> > > 
> > > (note, this driver is clause-22 only.)
> > > 
> > 
> > Had commented on the previous version (not sure why this was not
> > prefixed with v2) that the maximum clock frequency for this clock is
> > 250MHz, the driver could check that to prevent for an overflow, most
> > certainly.
> 
> Could also use:
> -	div = (rate / (2 * priv->clk_freq)) - 1;
> +	div = ((rate / priv->clk_freq) >> 1) - 1;
> which is mathematically equivalent without the risk of overflow.

What's the point when the maximum clock frequency that the driver should
allow fits within u32, nay u28?
Doug Berger March 12, 2024, 10:53 p.m. UTC | #6
On 3/12/2024 12:42 PM, Russell King (Oracle) wrote:
> On Tue, Mar 12, 2024 at 12:23:20PM -0700, Doug Berger wrote:
>> On 3/12/2024 10:23 AM, Florian Fainelli wrote:
>>> On 3/12/24 10:18, Russell King (Oracle) wrote:
>>>> On Tue, Mar 12, 2024 at 07:53:58PM +0300, Daniil Dulov wrote:
>>>>> The expression priv->clk_freq * 2 can lead to overflow that will cause
>>>>> a division by zero. So, let's cast it to unsigned long to avoid it.
>>>>
>>>> How does casting this help? "unsigned long" can still be 32-bit.
>>>> Maybe unimac_mdio_probe() should be validating the value it read from
>>>> DT won't overflow? I suspect that a value of 2.1GHz is way too large
>>>> for this property in any case.
>>>>
>>>> https://en.wikipedia.org/wiki/Management_Data_Input/Output#Electrical_specification
>>>>
>>>> (note, this driver is clause-22 only.)
>>>>
>>>
>>> Had commented on the previous version (not sure why this was not
>>> prefixed with v2) that the maximum clock frequency for this clock is
>>> 250MHz, the driver could check that to prevent for an overflow, most
>>> certainly.
>>
>> Could also use:
>> -	div = (rate / (2 * priv->clk_freq)) - 1;
>> +	div = ((rate / priv->clk_freq) >> 1) - 1;
>> which is mathematically equivalent without the risk of overflow.
> 
> What's the point when the maximum clock frequency that the driver should
> allow fits within u32, nay u28?
I'm assuming this question is rhetorical since I agree there is little 
point to this change.

However, in case it's not, the point is to make the SVACE tool happy. 
The tool has correctly identified that it is possible for the devicetree 
to specify values that would produce an intermediate overflow. The fact 
that there is no existing hardware for which those values are legitimate 
may be very relevant, but the binding documentation does not specify any 
such limitations and the future has a tendency to make numbers that seem 
ludicrous today less ludicrous ;). The brcm,unimac-mdio IP could find 
itself in some future piece of silicon where it would be capable of 
dividing such unlikely clocks since software has a knack for outliving 
the hardware for which it may have been originally written.

My suggestion was merely an attempt to remove the possibility of 
overflow (the unrealized bug) without altering existing functionality 
and without needlessly promoting to a larger data type.

Best regards,
     Doug
diff mbox series

Patch

diff --git a/drivers/net/mdio/mdio-bcm-unimac.c b/drivers/net/mdio/mdio-bcm-unimac.c
index f40eb50bb978..0425b622c09f 100644
--- a/drivers/net/mdio/mdio-bcm-unimac.c
+++ b/drivers/net/mdio/mdio-bcm-unimac.c
@@ -214,7 +214,7 @@  static int unimac_mdio_clk_set(struct unimac_mdio_priv *priv)
 	else
 		rate = clk_get_rate(priv->clk);
 
-	div = (rate / (2 * priv->clk_freq)) - 1;
+	div = (rate / (2 * (unsigned long)priv->clk_freq)) - 1;
 	if (div & ~MDIO_CLK_DIV_MASK) {
 		pr_warn("Incorrect MDIO clock frequency, ignoring\n");
 		ret = 0;