linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Rob Herring <robh@kernel.org>
To: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>,
	PCI <linux-pci@vger.kernel.org>,
	Anders Roxell <anders.roxell@linaro.org>,
	Arnd Bergmann <arnd@arndb.de>
Subject: Re: [PATCH 2/2] PCI: Fix pci_host_bridge struct device release/free handling
Date: Thu, 14 May 2020 07:50:43 -0500	[thread overview]
Message-ID: <CAL_JsqLC0MBgCxGmoGj7+JZec9ZWaBU5_BQibY9-nO35Jm+VcA@mail.gmail.com> (raw)
In-Reply-To: <20200514103028.GA16121@red-moon.cambridge.arm.com>

On Thu, May 14, 2020 at 5:30 AM Lorenzo Pieralisi
<lorenzo.pieralisi@arm.com> wrote:
>
> On Wed, May 13, 2020 at 05:38:59PM -0500, Rob Herring wrote:
> > The PCI code has several paths where the struct pci_host_bridge is freed
> > directly. This is wrong because it contains a struct device which is
> > refcounted and should be freed using put_device(). This can result in
> > use-after-free errors. I think this problem has existed since 2012 with
> > commit 7b5436635800 ("PCI: add generic device into pci_host_bridge
> > struct"). It generally hasn't mattered as most host bridge drivers are
> > still built-in and can't unbind.
> >
> > The problem is a struct device should never be freed directly once
> > device_initialize() is called and a ref is held, but that doesn't happen
> > until pci_register_host_bridge(). There's then a window between
> > allocating the host bridge and pci_register_host_bridge() where kfree
> > should be used. This is fragile and requires callers to do the right
> > thing. To fix this, we need to split device_register() into
> > device_initialize() and device_add() calls, so that the host bridge
> > struct is always freed by using a put_device().
> >
> > devm_pci_alloc_host_bridge() is using devm_kzalloc() to allocate struct
> > pci_host_bridge which will be freed directly. Instead, we can use a
> > custom devres action to call put_device().
> >
> > Reported-by: Anders Roxell <anders.roxell@linaro.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Bjorn Helgaas <bhelgaas@google.com>
> > Signed-off-by: Rob Herring <robh@kernel.org>
> > ---
> >  drivers/pci/probe.c  | 36 +++++++++++++++++++-----------------
> >  drivers/pci/remove.c |  2 +-
> >  2 files changed, 20 insertions(+), 18 deletions(-)

[...]

> > @@ -908,7 +910,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
> >       if (err)
> >               goto free;
> >
> > -     err = device_register(&bridge->dev);
> > +     err = device_add(&bridge->dev);
> >       if (err) {
> >               put_device(&bridge->dev);
> >               goto free;
> > @@ -978,7 +980,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
> >
> >  unregister:
> >       put_device(&bridge->dev);
> > -     device_unregister(&bridge->dev);
> > +     device_del(&bridge->dev);
>
> I think we need to execute device_del() first, then put_device().

No, because after the device_add, there's a get_device() adding the
bridge ptr to the bus. So the put_device here is for that. The final
put_device() is in the bridge free or devm action.

Rob

  reply	other threads:[~2020-05-14 12:50 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-13 22:38 [PATCH 1/2] PCI: Fix pci_register_host_bridge() device_register() error handling Rob Herring
2020-05-13 22:38 ` [PATCH 2/2] PCI: Fix pci_host_bridge struct device release/free handling Rob Herring
2020-05-14 10:27   ` Anders Roxell
2020-05-14 10:30   ` Lorenzo Pieralisi
2020-05-14 12:50     ` Rob Herring [this message]
2020-05-14 16:43   ` Lorenzo Pieralisi
2020-05-14 21:22   ` Arnd Bergmann
2020-05-14 16:41 ` [PATCH 1/2] PCI: Fix pci_register_host_bridge() device_register() error handling Lorenzo Pieralisi
2020-05-14 21:16 ` Arnd Bergmann
2020-05-14 21:37 ` Bjorn Helgaas

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=CAL_JsqLC0MBgCxGmoGj7+JZec9ZWaBU5_BQibY9-nO35Jm+VcA@mail.gmail.com \
    --to=robh@kernel.org \
    --cc=anders.roxell@linaro.org \
    --cc=arnd@arndb.de \
    --cc=bhelgaas@google.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.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).