From: Al Viro <viro@ZenIV.linux.org.uk>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-api@vger.kernel.org, linux-kernel@vger.kernel.org,
john.stultz@linaro.org, arnd@arndb.de, tj@kernel.org,
marcel@holtmann.org, desrt@desrt.ca, hadess@hadess.net,
dh.herrmann@gmail.com, tixxdz@opendz.org,
simon.mcvittie@collabora.co.uk, daniel@zonque.org,
alban.crequy@collabora.co.uk, javier.martinez@collabora.co.uk,
teg@jklm.no, Linus Torvalds <torvalds@linux-foundation.org>
Subject: How Not To Use kref (was Re: kdbus: add code for buses, domains and endpoints)
Date: Thu, 30 Oct 2014 23:38:01 +0000 [thread overview]
Message-ID: <20141030233801.GF7996@ZenIV.linux.org.uk> (raw)
In-Reply-To: <1414620056-6675-9-git-send-email-gregkh@linuxfoundation.org>
On Wed, Oct 29, 2014 at 03:00:52PM -0700, Greg Kroah-Hartman wrote:
> +static void __kdbus_domain_user_free(struct kref *kref)
> +{
> + struct kdbus_domain_user *user =
> + container_of(kref, struct kdbus_domain_user, kref);
> +
> + BUG_ON(atomic_read(&user->buses) > 0);
> + BUG_ON(atomic_read(&user->connections) > 0);
> +
> + mutex_lock(&user->domain->lock);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> + idr_remove(&user->domain->user_idr, user->idr);
> + hash_del(&user->hentry);
^^^^^^^^^^^^^^^^^^^^^^^^
> + mutex_unlock(&user->domain->lock);
> +
> + kdbus_domain_unref(user->domain);
> + kfree(user);
> +}
> +struct kdbus_domain_user *kdbus_domain_user_unref(struct kdbus_domain_user *u)
> +{
> + if (u)
> + kref_put(&u->kref, __kdbus_domain_user_free);
> + return NULL;
> +}
If you remove an object from some search structures, taking the lock in
destructor is Too Fucking Late(tm). Somebody might have already found
that puppy and decided to pick it (all under that lock) just as we'd
got to that point in destructor and blocked there. Oops...
Normally I'd say "just use kref_put_mutex()", but this case is even worse.
Look:
refcount is 1
A: kref_put_mutex()
see that it's potential 1->0 crossing, need to take mutex
mutex_lock()
B: kref_get()
refcount is 2
A: got the sodding mutex
atomic_dec_and_test
refcount is 1 now
OK, it's not 1->0, after all, just drop the mutex and bugger off
B: kref_put_mutex()
see that it's potential 1->0 crossing, need to take mutex
mutex_lock() blocks
A: mutex_unlock() lets B go
B: ... got it
atomic_dec_and_test
refcount is 0
call the destructor now, which ends with
kdbus_domain_unref(user->domain);
... which just happens to be the last reference to ->domain
... and frees it, along with ->domain->mutex
But what's to guarantee that A will be past the last point where mutex_unlock()
is looking at the mutex? Sure, it's hard to hit, but AFAICS it's not
impossible, especially if the following happens (assuming mutex-dec.h-style
mutices):
B: mutex_lock()
atomic_dec_return -> -1
__mutex_lock_slowpath()
A: mutex_unlock()
atomic_inc_return -> 0
get preempted
B: note that A has already incremented it to 0 and bugger off - we'd got it
and there we go, with A getting the timeslice back and deciding to call
__mutex_unlock_slowpath() when B has already freed the damn thing.
Basically, kref_put_mutex() is only usable when destructor callback cannot end
up freeing the mutex.
kref_get_unless_zero() might be a usable approach, but IMO the whole thing is
simply outside of kref applicability. Using it for something that needs to
deal with removal from search structures from the destructor callback is
already stretching the things; this one is far worse. kref isn't a universal
tool for expressing lifetime cycles. It works for really simple cases and
might eliminate some amount of boilerplate code. It's been greatly oversold
and overused, though...
next prev parent reply other threads:[~2014-10-30 23:38 UTC|newest]
Thread overview: 103+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-29 22:00 [PATCH 00/12] Add kdbus implementation Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add documentation Greg Kroah-Hartman
2014-10-30 12:20 ` Peter Meerwald
2014-11-02 1:29 ` Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add header file Greg Kroah-Hartman
2014-10-30 8:20 ` Arnd Bergmann
2014-10-30 11:02 ` Tom Gundersen
2014-10-30 11:26 ` Arnd Bergmann
2014-10-30 11:52 ` Daniel Mack
2014-10-30 12:03 ` Arnd Bergmann
2014-10-31 10:03 ` Daniel Mack
2014-10-29 22:00 ` kdbus: add driver skeleton, ioctl entry points and utility functions Greg Kroah-Hartman
2014-10-30 3:50 ` Eric W. Biederman
2014-10-30 23:45 ` Thomas Gleixner
2014-10-31 0:23 ` Jiri Kosina
2014-10-31 0:42 ` Thomas Gleixner
2014-10-29 22:00 ` kdbus: add connection pool implementation Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add connection, queue handling and message validation code Greg Kroah-Hartman
[not found] ` <87k33iw759.fsf@x220.int.ebiederm.org>
2014-10-30 3:55 ` Andy Lutomirski
2014-10-30 9:06 ` Djalal Harouni
2014-10-29 22:00 ` kdbus: add code to gather metadata Greg Kroah-Hartman
2014-10-29 22:33 ` Andy Lutomirski
2014-10-30 0:13 ` Andy Lutomirski
2014-10-30 8:45 ` Daniel Mack
2014-10-30 14:07 ` Andy Lutomirski
2014-10-30 15:54 ` Daniel Mack
2014-10-30 21:01 ` Andy Lutomirski
2014-11-01 11:05 ` Daniel Mack
2014-11-01 16:19 ` Andy Lutomirski
2014-11-03 12:00 ` Simon McVittie
2014-11-03 17:05 ` Andy Lutomirski
2014-10-30 8:09 ` Daniel Mack
2014-10-29 22:00 ` kdbus: add code for notifications and matches Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add code for buses, domains and endpoints Greg Kroah-Hartman
2014-10-30 3:59 ` Eric W. Biederman
2014-10-30 9:58 ` Djalal Harouni
2014-10-30 12:15 ` Eric W. Biederman
2014-10-30 14:48 ` Djalal Harouni
2014-10-30 14:58 ` Andy Lutomirski
2014-10-30 18:08 ` Djalal Harouni
2014-10-30 18:46 ` Simon McVittie
2014-11-05 19:59 ` Djalal Harouni
2014-10-30 20:37 ` Andy Lutomirski
[not found] ` <m2ublh$5h7$2@ger.gmane.org>
2014-10-30 22:00 ` Andy Lutomirski
2014-10-30 23:38 ` Al Viro [this message]
2014-10-31 18:00 ` How Not To Use kref (was Re: kdbus: add code for buses, domains and endpoints) Linus Torvalds
2014-10-31 19:56 ` Al Viro
2014-11-04 9:11 ` David Herrmann
2014-10-31 1:39 ` kdbus: add code for buses, domains and endpoints Al Viro
2014-10-31 9:55 ` Daniel Mack
2014-10-29 22:00 ` kdbus: add name registry implementation Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add policy database implementation Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add Makefile, Kconfig and MAINTAINERS entry Greg Kroah-Hartman
2014-10-29 22:00 ` kdbus: add selftests Greg Kroah-Hartman
2014-10-30 8:31 ` Arnd Bergmann
2014-11-14 3:42 ` Michael Ellerman
2014-11-14 8:56 ` Daniel Mack
2014-10-29 22:15 ` [PATCH 00/12] Add kdbus implementation Greg KH
2014-10-30 4:04 ` Eric W. Biederman
2014-10-30 7:12 ` Daniel Mack
2014-10-29 22:15 ` Andy Lutomirski
2014-10-29 22:27 ` Greg Kroah-Hartman
2014-10-29 22:34 ` Andy Lutomirski
2014-10-30 2:27 ` Andy Lutomirski
2014-10-30 4:20 ` Eric W. Biederman
2014-10-30 10:15 ` Tom Gundersen
2014-10-30 12:02 ` Eric W. Biederman
2014-10-30 13:48 ` Andy Lutomirski
2014-10-29 22:19 ` Andy Lutomirski
2014-10-29 22:25 ` Greg Kroah-Hartman
2014-10-29 22:28 ` Andy Lutomirski
2014-10-29 22:36 ` Andy Lutomirski
2014-10-30 7:44 ` Daniel Mack
2014-11-05 14:34 ` Daniel Mack
2014-10-29 23:00 ` Jiri Kosina
2014-10-29 23:11 ` Greg Kroah-Hartman
2014-10-29 23:12 ` Greg Kroah-Hartman
2014-10-29 23:24 ` Jiri Kosina
2014-10-29 23:26 ` Jiri Kosina
2014-10-29 23:34 ` Greg Kroah-Hartman
2014-10-29 23:40 ` Greg Kroah-Hartman
2014-10-29 23:55 ` Andy Lutomirski
2014-10-30 11:52 ` Tom Gundersen
2014-10-30 12:28 ` Simon McVittie
2014-10-30 13:59 ` Andy Lutomirski
2014-10-30 20:28 ` Alex Elsayed
2014-10-30 9:51 ` Karol Lewandowski
2014-10-30 10:44 ` Karol Lewandowski
2014-10-30 14:47 ` Greg Kroah-Hartman
2014-10-30 19:55 ` Karol Lewandowski
2014-10-30 20:24 ` Greg Kroah-Hartman
2014-10-31 11:15 ` Karol Lewandowski
2014-10-30 23:13 ` One Thousand Gnomes
2014-10-31 10:58 ` Karol Lewandowski
2014-10-30 23:39 ` Paul Moore
2014-10-31 14:21 ` Karol Lewandowski
[not found] ` <1414773397-26490-1-git-send-email-k.lewandowsk@samsung.com>
[not found] ` <20141107180120.GA15387@kroah.com>
2014-11-09 0:07 ` [RFC PATCH 0/5] kdbus: add support for lsm Karol Lewandowski
[not found] ` <1414773397-26490-2-git-send-email-k.lewandowsk@samsung.com>
2014-11-17 1:47 ` [PATCH 1/5] kdbus: extend structures with security pointer " Karol Lewandowski
2014-11-17 18:37 ` Greg KH
2014-11-02 1:21 ` [PATCH 00/12] Add kdbus implementation Greg Kroah-Hartman
2014-11-03 14:38 ` One Thousand Gnomes
2014-10-30 8:33 ` Arnd Bergmann
2014-10-30 16:17 ` Greg Kroah-Hartman
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=20141030233801.GF7996@ZenIV.linux.org.uk \
--to=viro@zeniv.linux.org.uk \
--cc=alban.crequy@collabora.co.uk \
--cc=arnd@arndb.de \
--cc=daniel@zonque.org \
--cc=desrt@desrt.ca \
--cc=dh.herrmann@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=hadess@hadess.net \
--cc=javier.martinez@collabora.co.uk \
--cc=john.stultz@linaro.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marcel@holtmann.org \
--cc=simon.mcvittie@collabora.co.uk \
--cc=teg@jklm.no \
--cc=tixxdz@opendz.org \
--cc=tj@kernel.org \
--cc=torvalds@linux-foundation.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
Powered by JetHome