mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* docs: bug in "Krefs and RCU" example
@ 2024-03-18 11:27 Dmitry Mastykin
  2024-03-19  3:36 ` Matthew Wilcox
  0 siblings, 1 reply; 2+ messages in thread
From: Dmitry Mastykin @ 2024-03-18 11:27 UTC (permalink / raw)
  To: corbet, linux-doc, linux-kernel, thellstrom; +Cc: mastichi, Dmitry Mastykin

Hello all,
It seems there is a problem in "Krefs and RCU" example, that may cause
a crash.
I marked the place between two problem lines with "problem is here" comment.
If list_del_rcu() will be called between these lines, and list will become
empty, then q.next will not point to a valid struct my_data.
entry->refcount will also be invalid.
Instead, q.next must be read first, and then compared with q to check
list's emptiness (for example like in list_for_each_entry_rcu macro).

Signed-off-by: Dmitry Mastykin <dmastykin@astralinux.ru>

diff --git a/Documentation/core-api/kref.rst b/Documentation/core-api/kref.rst
index c61eea6f1bf2..b76d71d9c9a0 100644
--- a/Documentation/core-api/kref.rst
+++ b/Documentation/core-api/kref.rst
@@ -274,44 +274,45 @@ return value. If you are sure (by already having a valid pointer) that
 kref_get_unless_zero() will return true, then use kref_get() instead.
 
 Krefs and RCU
 =============
 
 The function kref_get_unless_zero also makes it possible to use rcu
 locking for lookups in the above example::
 
 	struct my_data
 	{
 		struct rcu_head rhead;
 		.
 		struct kref refcount;
 		.
 		.
 	};
 
 	static struct my_data *get_entry_rcu()
 	{
 		struct my_data *entry = NULL;
 		rcu_read_lock();
 		if (!list_empty(&q)) {
+			// problem is here
 			entry = container_of(q.next, struct my_data, link);
 			if (!kref_get_unless_zero(&entry->refcount))
 				entry = NULL;
 		}
 		rcu_read_unlock();
 		return entry;
 	}
 
 	static void release_entry_rcu(struct kref *ref)
 	{
 		struct my_data *entry = container_of(ref, struct my_data, refcount);
 
 		mutex_lock(&mutex);
 		list_del_rcu(&entry->link);
 		mutex_unlock(&mutex);
 		kfree_rcu(entry, rhead);
 	}
 
 	static void put_entry(struct my_data *entry)
 	{
 		kref_put(&entry->refcount, release_entry_rcu);
 	}

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-03-19  3:36 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-18 11:27 docs: bug in "Krefs and RCU" example Dmitry Mastykin
2024-03-19  3:36 ` Matthew Wilcox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®