All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: linux-nvdimm <linux-nvdimm@lists.01.org>
Subject: Re: [bug report] libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver infrastructure
Date: Wed, 5 Feb 2020 22:08:45 +0300	[thread overview]
Message-ID: <20200205190845.GD24804@kadam> (raw)
In-Reply-To: <CAPcyv4itFypOmv38Oo=DRWk_1Y3PFhPpYPDzxShmZVY9ZsTNLA@mail.gmail.com>

On Wed, Feb 05, 2020 at 10:23:00AM -0800, Dan Williams wrote:
> > > >    506          if (device_add(dev) != 0) {
> > > >    507                  dev_err(dev, "%s: failed\n", __func__);
> > > >    508                  put_device(dev);
> > > >                         ^^^^^^^^^^^^^^^
> > > >    509          }
> > > >    510          put_device(dev);
> > > >                 ^^^^^^^^^^^^^^
> > > >    511          if (dev->parent)
> > > >    512                  put_device(dev->parent);
> > > >    513  }
> > > >
> > > > We call get_device() from __nd_device_register(), I guess.  It seems
> > > > buggy to call put device twice on error.
> > >
> > > The registration path does:
> > >
> > >         get_device(dev);
> > >
> > >         async_schedule_dev_domain(nd_async_device_register, dev,
> > >                                   &nd_async_domain);
> > >
> > > ...and device_add() does its own get_device().
> >
> > device_add() does its own put_device() at the end so it's a net zero.
> >
> 
> It does it's own, yes, but the put_device() after device_add() failure
> is there to drop the reference taken by device_initialize().
> Otherwise, device_add() has always documented:
> 
>  * NOTE: _Never_ directly free @dev after calling this function, even
>  * if it returned an error! Always use put_device() to give up your
>  * reference instead.
> 
> ...so what am I missing?

The "never call kfree" is hopefully straight forward because the kobject
needs to do its own cleanup.

__nvdimm_create() allocates the dev.
nd_device_register() calls device_initialize() which call kobject_init()
   so the refcount is 1.
__nd_device_register() call get_device() so the refcount is now two.
nd_async_device_register() decrements the refcount once on success.

But if device_add() fails then it decrements it twice.  Now the refcount
is zero so we call nvdimm_release().  This leads to a use after free on
the next line:

	put_device(dev);
	if (dev->parent)

There is a trick here because depending on the debug options it
might free immediately or it might call nvdimm_release() after 4
seconds.  See kobject_release() for details.

Either way if device_add() fails we return back to __nvdimm_create()
and return the zero reference count "nvdimm" pointer, which is going
to be a problem.

regards,
dan carpenter
_______________________________________________
Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

  reply	other threads:[~2020-02-05 19:08 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-05 12:38 [bug report] libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver infrastructure Dan Carpenter
2020-02-05 17:47 ` Dan Williams
2020-02-05 18:10   ` Dan Carpenter
2020-02-05 18:23     ` Dan Williams
2020-02-05 19:08       ` Dan Carpenter [this message]
2020-02-05 19:16         ` Dan Williams
2020-02-05 19:28           ` Dan Carpenter
2020-02-05 20:04             ` Dan Williams
2020-02-05 20:18               ` Dan Carpenter

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=20200205190845.GD24804@kadam \
    --to=dan.carpenter@oracle.com \
    --cc=dan.j.williams@intel.com \
    --cc=linux-nvdimm@lists.01.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.