All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Dumazet <eric.dumazet@gmail.com>
To: Jia-Ju Bai <baijiaju1990@gmail.com>,
	Eric Dumazet <eric.dumazet@gmail.com>,
	davem@davemloft.net, fthain@telegraphics.com.au, joe@perches.com
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] net: 8390: Fix possible data races in __ei_get_stats
Date: Mon, 7 May 2018 18:56:29 -0700	[thread overview]
Message-ID: <c336fdb9-4865-4729-d34b-84dd0bfc9af5@gmail.com> (raw)
In-Reply-To: <d4de4f6c-c697-fde5-9d31-d8792621bfb5@gmail.com>



On 05/07/2018 05:51 PM, Jia-Ju Bai wrote:
> 
> 
> On 2018/5/7 22:15, Eric Dumazet wrote:
>>
>> On 05/07/2018 07:08 AM, Jia-Ju Bai wrote:
>>> The write operations to "dev->stats" are protected by
>>> the spinlock on line 862-864, but the read operations to
>>> this data on line 858 and 867 are not protected by the spinlock.
>>> Thus, there may exist data races for "dev->stats".
>>>
>>> To fix the data races, the read operations to "dev->stats" are
>>> protected by the spinlock, and a local variable is used for return.
>>>
>>> Signed-off-by: Jia-Ju Bai <baijiaju1990@gmail.com>
>>> ---
>>>   drivers/net/ethernet/8390/lib8390.c | 14 ++++++++++----
>>>   1 file changed, 10 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
>>> index c9c55c9eab9f..198952247d30 100644
>>> --- a/drivers/net/ethernet/8390/lib8390.c
>>> +++ b/drivers/net/ethernet/8390/lib8390.c
>>> @@ -852,19 +852,25 @@ static struct net_device_stats *__ei_get_stats(struct net_device *dev)
>>>       unsigned long ioaddr = dev->base_addr;
>>>       struct ei_device *ei_local = netdev_priv(dev);
>>>       unsigned long flags;
>>> +    struct net_device_stats *stats;
>>> +
>>> +    spin_lock_irqsave(&ei_local->page_lock, flags);
>>>         /* If the card is stopped, just return the present stats. */
>>> -    if (!netif_running(dev))
>>> -        return &dev->stats;
>>> +    if (!netif_running(dev)) {
>>> +        stats = &dev->stats;
>>> +        spin_unlock_irqrestore(&ei_local->page_lock, flags);
>>> +        return stats;
>>> +    }
>>>   -    spin_lock_irqsave(&ei_local->page_lock, flags);
>>>       /* Read the counter registers, assuming we are in page 0. */
>>>       dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
>>>       dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
>>>       dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
>>> +    stats = &dev->stats;
>>>       spin_unlock_irqrestore(&ei_local->page_lock, flags);
>>>   -    return &dev->stats;
>>> +    return stats;
>>>   }
>>>     /*
>>>
>> dev->stats is not a pointer, it is an array embedded in the
>> struct net_device
>>
>> So this patch is not needed, since dev->stats can not change.
> 
> Thanks for your reply :)
> 
> I do not understand that why "dev->stats can not change".
> Its data is indeed changed by the code:
>      dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
>      dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
>      dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);

So ?

> 
> So I think a data race may occur when returning "dev->stats" without lock protection.

&dev->stats is a stable value.

It wont change over the lifetime of net_device object.

Adding a barrier before or after getting &dev->stats is useless, confusing and really not needed.



> 
> By the way, I find this possible data race is similar to the previous commit 7b31b4deda76 for the tg3 driver.

Very different things really.

This does a copy of the whole stats, not the pointer :

*stats = tp->net_stats_prev;


I guess you are confusing simple C semantics about returning the address of a structure,
instead of returning a whole structure.

If __ei_get_stats(struct net_device *dev) prototype was :

struct net_device_stats __ei_get_stats(struct net_device *dev) 

instead of :

struct net_device_stats *__ei_get_stats(struct net_device *dev) 

Then sure, your patch might been needed.

  reply	other threads:[~2018-05-08  1:56 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-07 14:08 [PATCH] net: 8390: Fix possible data races in __ei_get_stats Jia-Ju Bai
2018-05-07 14:15 ` Eric Dumazet
2018-05-08  0:51   ` Jia-Ju Bai
2018-05-08  1:56     ` Eric Dumazet [this message]
2018-05-08  2:16       ` Jia-Ju Bai
2018-05-08  5:04         ` Eric Dumazet
2018-05-08  6:47           ` Jia-Ju Bai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c336fdb9-4865-4729-d34b-84dd0bfc9af5@gmail.com \
    --to=eric.dumazet@gmail.com \
    --cc=baijiaju1990@gmail.com \
    --cc=davem@davemloft.net \
    --cc=fthain@telegraphics.com.au \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.