From: Hans Verkuil <hansverk-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
To: Logan Gunthorpe <logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>,
Greg Kroah-Hartman
<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
Dan Williams
<dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Alexander Viro
<viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>,
Johannes Thumshirn <jthumshirn-l3A5Bk7waGM@public.gmane.org>,
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>,
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
Sajjan Vikas C <vikas.cha.sajjan-ZPxbGqLxI0U@public.gmane.org>,
Dmitry Torokhov
<dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Linus Walleij
<linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Alexandre Courbot
<gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
Peter Huewe <peterhuewe-Mmb7MZpHnFY@public.gmane.org>,
Marcel Selhorst <tpmdd-yWjUBOtONefk1uMJSBkQmQ@public.gmane.org>,
Jarkko Sakkinen
<jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>,
Jason Gunthorpe
<jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>,
Olof Johansson <olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org>,
Doug Ledford <dledford-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
Sean Hefty <sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
Hal Rosenstock
<hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>Dmitry
Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v2 01/16] chardev: add helper function to register char devs with a struct device
Date: Mon, 27 Feb 2017 10:01:23 +0100 [thread overview]
Message-ID: <c25a3d35-5570-ac9c-7b51-92dd6383f1f8@cisco.com> (raw)
In-Reply-To: <1488091097-12328-2-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
On 02/26/2017 07:38 AM, Logan Gunthorpe wrote:
> Credit for this patch goes is shared with Dan Williams [1]. I've
> taken things one step further to make the helper function more
> useful and clean up calling code.
>
> There's a common pattern in the kernel whereby a struct cdev is placed
> in a structure along side a struct device which manages the life-cycle
> of both. In the naive approach, the reference counting is broken and
> the struct device can free everything before the chardev code
> is entirely released.
>
> Many developers have solved this problem by linking the internal kobjs
> in this fashion:
>
> cdev.kobj.parent = &parent_dev.kobj;
>
> The cdev code explicitly gets and puts a reference to it's kobj parent.
> So this seems like it was intended to be used this way. Dmitrty Torokhov
> first put this in place in 2012 with this commit:
>
> 2f0157f char_dev: pin parent kobject
>
> and the first instance of the fix was then done in the input subsystem
> in the following commit:
>
> 4a215aa Input: fix use-after-free introduced with dynamic minor changes
>
> Subsequently over the years, however, this issue seems to have tripped
> up multiple developers independently. For example, see these commits:
>
> 0d5b7da iio: Prevent race between IIO chardev opening and IIO device
> (by Lars-Peter Clausen in 2013)
>
> ba0ef85 tpm: Fix initialization of the cdev
> (by Jason Gunthorpe in 2015)
>
> 5b28dde [media] media: fix use-after-free in cdev_put() when app exits
> after driver unbind
> (by Shauh Khan in 2016)
>
> This technique is similarly done in at least 15 places within the kernel
> and probably should have been done so in another, at least, 5 places.
> The kobj line also looks very suspect in that one would not expect
> drivers to have to mess with kobject internals in this way.
> Even highly experienced kernel developers can be surprised by this
> code, as seen in [2].
>
> To help alleviate this situation, and hopefully prevent future
> wasted effort on this problem, this patch introduces a helper function
> to register a char device along with its parent struct device.
> This creates a more regular API for tying a char device to its parent
> without the developer having to set members in the underlying kobject.
>
> This patch introduce cdev_device_add and cdev_device_del which
> replaces a common pattern including setting the kobj parent, calling
> cdev_add and then calling device_add. It also introduces cdev_set_parent
> for the few cases that set the kobject parent without using device_add.
>
> [1] https://lkml.org/lkml/2017/2/13/700
> [2] https://lkml.org/lkml/2017/2/10/370
>
> Signed-off-by: Logan Gunthorpe <logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Reviewed-by: Hans Verkuil <hans.verkuil-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
Nice!
Regards,
Hans
> ---
> fs/char_dev.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/cdev.h | 4 ++++
> 2 files changed, 71 insertions(+)
>
> diff --git a/fs/char_dev.c b/fs/char_dev.c
> index 44a240c..471d480 100644
> --- a/fs/char_dev.c
> +++ b/fs/char_dev.c
> @@ -471,6 +471,70 @@ int cdev_add(struct cdev *p, dev_t dev, unsigned count)
> return 0;
> }
>
> +/**
> + * cdev_set_parent() - set the parent kobject for a char device
> + * @p: the cdev structure
> + * @kobj: the kobject to take a reference to
> + *
> + * cdev_set_parent() sets a parent kobject which will be referenced
> + * appropriately so the parent is not freed before the cdev. This
> + * should be called before cdev_add.
> + */
> +void cdev_set_parent(struct cdev *p, struct kobject *kobj)
> +{
> + WARN_ON(!kobj->state_initialized);
> + p->kobj.parent = kobj;
> +}
> +
> +/**
> + * cdev_device_add() - add a char device and it's corresponding
> + * struct device, linkink
> + * @dev: the device structure
> + * @cdev: the cdev structure
> + *
> + * cdev_device_add() adds the char device represented by @cdev to the system,
> + * just as cdev_add does. It then adds @dev to the system using device_add
> + * The dev_t for the char device will be taken from the struct device which
> + * needs to be initialized first. This helper function correctly takes a
> + * reference to the parent device so the parent will not get released until
> + * all references to the cdev are released.
> + *
> + * This function should be used whenever the struct cdev and the
> + * struct device are members of the same structure whose lifetime is
> + * managed by the struct device.
> + */
> +int cdev_device_add(struct cdev *cdev, struct device *dev)
> +{
> + int rc = 0;
> +
> + cdev_set_parent(cdev, &dev->kobj);
> +
> + rc = cdev_add(cdev, dev->devt, 1);
> + if (rc)
> + return rc;
> +
> + rc = device_add(dev);
> + if (rc)
> + cdev_del(cdev);
> +
> + return rc;
> +}
> +
> +/**
> + * cdev_device_del() - inverse of cdev_device_add
> + * @dev: the device structure
> + * @cdev: the cdev structure
> + *
> + * cdev_device_del() is a helper function to call cdev_del
> + * and device_del. It should be used whenever cdev_device_add
> + * is used.
> + */
> +void cdev_device_del(struct cdev *cdev, struct device *dev)
> +{
> + device_del(dev);
> + cdev_del(cdev);
> +}
> +
> static void cdev_unmap(dev_t dev, unsigned count)
> {
> kobj_unmap(cdev_map, dev, count);
> @@ -570,5 +634,8 @@ EXPORT_SYMBOL(cdev_init);
> EXPORT_SYMBOL(cdev_alloc);
> EXPORT_SYMBOL(cdev_del);
> EXPORT_SYMBOL(cdev_add);
> +EXPORT_SYMBOL(cdev_set_parent);
> +EXPORT_SYMBOL(cdev_device_add);
> +EXPORT_SYMBOL(cdev_device_del);
> EXPORT_SYMBOL(__register_chrdev);
> EXPORT_SYMBOL(__unregister_chrdev);
> diff --git a/include/linux/cdev.h b/include/linux/cdev.h
> index f876361..4c99579 100644
> --- a/include/linux/cdev.h
> +++ b/include/linux/cdev.h
> @@ -26,6 +26,10 @@ void cdev_put(struct cdev *p);
>
> int cdev_add(struct cdev *, dev_t, unsigned);
>
> +void cdev_set_parent(struct cdev *p, struct kobject *kobj);
> +int cdev_device_add(struct cdev *cdev, struct device *dev);
> +void cdev_device_del(struct cdev *cdev, struct device *dev);
> +
> void cdev_del(struct cdev *);
>
> void cd_forget(struct inode *);
>
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
next prev parent reply other threads:[~2017-02-27 9:01 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-26 6:38 [PATCH v2 00/16] Cleanup chardev instances with helper function Logan Gunthorpe
[not found] ` <1488091097-12328-1-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-26 6:38 ` [PATCH v2 01/16] chardev: add helper function to register char devs with a struct device Logan Gunthorpe
[not found] ` <1488091097-12328-2-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-26 18:21 ` Dan Williams
[not found] ` <CAPcyv4i91_esBtBxbnDH3ZDd8Mnz4HoJEW2yeEvQ4QikFBjapA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-02-27 16:56 ` Jason Gunthorpe
[not found] ` <20170227165618.GE5891-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org>
2017-02-28 3:27 ` Logan Gunthorpe
[not found] ` <7df6e57b-531c-1b23-05bf-c368df2d20f3-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-28 3:36 ` Dan Williams
[not found] ` <CAPcyv4jiPE1jK9ubbsAm_ZNMt=S106NCpXD4KPUWpcK9_GEDJA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2017-02-28 5:31 ` Greg Kroah-Hartman
2017-02-27 9:01 ` Hans Verkuil [this message]
2017-02-27 9:47 ` Alexandre Belloni
2017-02-26 6:38 ` [PATCH v2 02/16] device-dax: fix cdev leak Logan Gunthorpe
[not found] ` <1488091097-12328-3-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-26 18:22 ` Dan Williams
2017-02-26 6:38 ` [PATCH v2 03/16] device-dax: utilize new cdev_device_add helper function Logan Gunthorpe
[not found] ` <1488091097-12328-4-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-26 22:31 ` Dan Williams
2017-02-26 6:38 ` [PATCH v2 04/16] input: " Logan Gunthorpe
[not found] ` <1488091097-12328-5-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-28 18:27 ` Dmitry Torokhov
2017-02-26 6:38 ` [PATCH v2 05/16] gpiolib: " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 06/16] tpm-chip: " Logan Gunthorpe
[not found] ` <1488091097-12328-7-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-27 16:42 ` Jason Gunthorpe
2017-02-26 6:38 ` [PATCH v2 07/16] platform/chrome: cros_ec_dev - " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 08/16] IB/ucm: " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 09/16] infiniband: utilize the new cdev_set_parent function Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 10/16] iio:core: utilize new cdev_device_add helper function Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 11/16] media: " Logan Gunthorpe
[not found] ` <1488091097-12328-12-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-27 9:02 ` Hans Verkuil
[not found] ` <8eff8408-1681-a59d-3b61-8fd5dab73af1-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
2017-03-04 22:57 ` Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 12/16] mtd: " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 13/16] rapidio: " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 14/16] rtc: " Logan Gunthorpe
[not found] ` <1488091097-12328-15-git-send-email-logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org>
2017-02-27 9:46 ` Alexandre Belloni
2017-02-26 6:38 ` [PATCH v2 15/16] scsi: " Logan Gunthorpe
2017-02-26 6:38 ` [PATCH v2 16/16] switchtec: utilize new device_add_cdev " Logan Gunthorpe
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=c25a3d35-5570-ac9c-7b51-92dd6383f1f8@cisco.com \
--to=hansverk-fyb4gu1cfyuavxtiumwx3w@public.gmane.org \
--cc=arnd-r2nGTMty4D4@public.gmane.org \
--cc=dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=dledford-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=gnurou-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
--cc=hal.rosenstock-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=jack-AlSwsSmVLrQ@public.gmane.org \
--cc=jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org \
--cc=jgunthorpe-ePGOBjL8dl3ta4EC/59zMFaTQe2KTcn/@public.gmane.org \
--cc=jthumshirn-l3A5Bk7waGM@public.gmane.org \
--cc=linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-media-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org \
--cc=linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-scsi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=logang-OTvnGxWRz7hWk0Htik3J/w@public.gmane.org \
--cc=olof-nZhT3qVonbNeoWH0uzbU5w@public.gmane.org \
--cc=peterhuewe-Mmb7MZpHnFY@public.gmane.org \
--cc=rtc-linux-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org \
--cc=sean.hefty-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=tpmdd-yWjUBOtONefk1uMJSBkQmQ@public.gmane.org \
--cc=vikas.cha.sajjan-ZPxbGqLxI0U@public.gmane.org \
--cc=viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.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 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).