netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Russell King (Oracle)" <linux@armlinux.org.uk>
To: Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: Andrew Lunn <andrew@lunn.ch>,
	Heiner Kallweit <hkallweit1@gmail.com>,
	Jiawen Wu <jiawenwu@trustnetic.com>,
	Maxime Chevallier <maxime.chevallier@bootlin.com>,
	Simon Horman <simon.horman@corigine.com>,
	netdev@vger.kernel.org
Subject: Re: [PATCH net-next 1/6] net: mdio: add mdio_device_get() and mdio_device_put()
Date: Mon, 29 May 2023 23:41:53 +0100	[thread overview]
Message-ID: <ZHUqMSXp2ZJOvs4n@shell.armlinux.org.uk> (raw)
In-Reply-To: <CAHp75Ve3+LsLA1x+zBLCxt7M3f1tL0bUquiG3o8-=0V3gs5_pw@mail.gmail.com>

On Mon, May 29, 2023 at 11:34:42PM +0300, Andy Shevchenko wrote:
> On Mon, May 29, 2023 at 6:21 PM Andrew Lunn <andrew@lunn.ch> wrote:
> > On Fri, May 26, 2023 at 09:20:17PM +0300, andy.shevchenko@gmail.com wrote:
> > > Fri, May 26, 2023 at 11:14:24AM +0100, Russell King (Oracle) kirjoitti:
> 
> ...
> 
> > > > +static inline void mdio_device_get(struct mdio_device *mdiodev)
> > > > +{
> > > > +   get_device(&mdiodev->dev);
> > >
> > > Dunno what is the practice in net, but it makes sense to have the pattern as
> > >
> > >       if (mdiodev)
> > >               return to_mdiodev(get_device(&mdiodev->dev));
> > >
> > > which might be helpful in some cases. This approach is used in many cases in
> > > the kernel.
> >
> > The device should exist. If it does not, it is a bug, and the
> > resulting opps will help find the bug.
> 
> The main point in the returned value, the 'if' can be dropped, it's
> not a big deal.

And if you do, that results in a latent bug.

The whole point of doing the above is to cater for the case when
mdiodev is NULL. If mdiodev is NULL, provided "dev" is the first member
of mdiodev, then &mdiodev->dev will also be NULL. That will mean
get_device() will see a NULL pointer and itself return NULL. The
to_mdiodev() will then convert back to a mdiodev which will also be
NULL. So everything works correctly.

If dev is not the first member, then &mdiodev->dev will no longer be
NULL, but will be offset by that amount.

get_device() will check whether that is NULL - it won't be, so it'll
try to pass &dev->kobj to kobject_get(). That will also not be a NULL
pointer. kobject_get() will likely oops the kernel.

So no, it isn't safe to drop that if().

However, count the number of places in the kernel that actually pay
attention to the return value of get_device()...

In drivers/base, which should be the prime area where things are
done correctly, there are 42 places where get_device() is called.
Of those 42 places, 13 places make use of the returned value in
some way, which mean 29 do not bother to check.

Now, what use is checking that return value? Does get_device()
ever return anything different from what was passed in?

Well, we need to delve further down into kobject_get(), which
does not - kobject_get() returns whatever it was given. Note
that kref_get() doesn't return anything, nor does refcount_inc(),
both of which post-date get_device().

So, that in turn means that get_device() will only ever return
what it was passed. So:

	ret = get_device(dev);

`ret' is _guaranteed_ to always be exactly the same was `dev' in
all cases (except if "dev" results in get_device() performing an
invalid dereference and Oopsing the kernel, by which time we won't
care about `ret'.)

Now, if we think about situations where this will be called - they
will always be called where the MDIO device already has reference
counts against it - we have to be holding at least one refcount
to already have a reference to this device. If we don't have that,
then we're in the situation where the memory pointed to by the
mdio device pointer has probably already been freed, and could
already be used for some other purpose - and using the return value
from get_device() isn't going to save you from such a racy stupidity.

If we extend this to mdio_device_get(), then we end up in exactly
the same scenario - and what benefit does it give to the code?
Does it make the code more readable? No, it makes it less readable.
Does it make the code more robust? No, it makes no difference.
Does it make the code more correct? Again, no difference.

So, I don't see any point in changing the proposal I've put forward
as mdio_device_get().

Things would be different if get_device() used kobject_get_unless_zero()
which _can_ alter the returned value, but as I've stated above, if the
refcount were to become zero at the point that mdio_device_get() may
be called, we've *already* lost.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

  reply	other threads:[~2023-05-29 22:42 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-26 10:13 [PATCH net-next 0/6] net: pcs: add helpers to xpcs and lynx to manage mdiodev Russell King (Oracle)
2023-05-26 10:14 ` [PATCH net-next 1/6] net: mdio: add mdio_device_get() and mdio_device_put() Russell King (Oracle)
2023-05-26 18:20   ` andy.shevchenko
2023-05-29 15:21     ` Andrew Lunn
2023-05-29 20:34       ` Andy Shevchenko
2023-05-29 22:41         ` Russell King (Oracle) [this message]
2023-05-29 15:18   ` Andrew Lunn
2023-05-26 10:14 ` [PATCH net-next 2/6] net: pcs: xpcs: add xpcs_create_mdiodev() Russell King (Oracle)
2023-05-29 15:25   ` Andrew Lunn
2023-05-29 16:05     ` Russell King (Oracle)
2023-05-29 16:27     ` Vladimir Oltean
2023-05-26 10:14 ` [PATCH net-next 3/6] net: stmmac: use xpcs_create_mdiodev() Russell King (Oracle)
2023-05-29 15:26   ` Andrew Lunn
2023-05-26 10:14 ` [PATCH net-next 4/6] net: pcs: lynx: add lynx_pcs_create_mdiodev() Russell King (Oracle)
2023-05-26 18:22   ` andy.shevchenko
2023-05-29 15:28   ` Andrew Lunn
2023-05-29 17:08   ` Ioana Ciornei
2023-05-26 10:14 ` [PATCH net-next 5/6] net: dsa: ocelot: use lynx_pcs_create_mdiodev() Russell King (Oracle)
2023-05-29 15:28   ` Andrew Lunn
2023-05-29 15:47   ` Vladimir Oltean
2023-05-26 10:14 ` [PATCH net-next 6/6] net: enetc: " Russell King (Oracle)
2023-05-29 15:29   ` Andrew Lunn
2023-05-29 15:46   ` Vladimir Oltean
2023-05-30  5:00 ` [PATCH net-next 0/6] net: pcs: add helpers to xpcs and lynx to manage mdiodev patchwork-bot+netdevbpf

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=ZHUqMSXp2ZJOvs4n@shell.armlinux.org.uk \
    --to=linux@armlinux.org.uk \
    --cc=andrew@lunn.ch \
    --cc=andy.shevchenko@gmail.com \
    --cc=hkallweit1@gmail.com \
    --cc=jiawenwu@trustnetic.com \
    --cc=maxime.chevallier@bootlin.com \
    --cc=netdev@vger.kernel.org \
    --cc=simon.horman@corigine.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).