[ 3.8.y.z extended stable ] Patch "rculist: list_first_or_null_rcu() should use list_entry_rcu()" has been added to staging queue
Kamal Mostafa
kamal at canonical.com
Thu Sep 19 00:03:25 UTC 2013
This is a note to let you know that I have just added a patch titled
rculist: list_first_or_null_rcu() should use list_entry_rcu()
to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree
which can be found at:
http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue
This patch is scheduled to be released in version 3.8.13.10.
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Kamal
------
>From fe11b83ac479766db81905348477c7dcbb23765c Mon Sep 17 00:00:00 2001
From: Tejun Heo <tj at kernel.org>
Date: Fri, 28 Jun 2013 10:34:48 -0700
Subject: rculist: list_first_or_null_rcu() should use list_entry_rcu()
commit c34ac00caefbe49d40058ae7200bd58725cebb45 upstream.
list_first_or_null() should test whether the list is empty and return
pointer to the first entry if not in a RCU safe manner. It's broken
in several ways.
* It compares __kernel @__ptr with __rcu @__next triggering the
following sparse warning.
net/core/dev.c:4331:17: error: incompatible types in comparison expression (different address spaces)
* It doesn't perform rcu_dereference*() and computes the entry address
using container_of() directly from the __rcu pointer which is
inconsitent with other rculist interface. As a result, all three
in-kernel users - net/core/dev.c, macvlan, cgroup - are buggy. They
dereference the pointer w/o going through read barrier.
* While ->next dereference passes through list_next_rcu(), the
compiler is still free to fetch ->next more than once and thus
nullify the "__ptr != __next" condition check.
Fix it by making list_first_or_null_rcu() dereference ->next directly
using ACCESS_ONCE() and then use list_entry_rcu() on it like other
rculist accessors.
v2: Paul pointed out that the compiler may fetch the pointer more than
once nullifying the condition check. ACCESS_ONCE() added on
->next dereference.
v3: Restored () around macro param which was accidentally removed.
Spotted by Paul.
Signed-off-by: Tejun Heo <tj at kernel.org>
Reported-by: Fengguang Wu <fengguang.wu at intel.com>
Cc: Dipankar Sarma <dipankar at in.ibm.com>
Cc: "Paul E. McKenney" <paulmck at linux.vnet.ibm.com>
Cc: "David S. Miller" <davem at davemloft.net>
Cc: Li Zefan <lizefan at huawei.com>
Cc: Patrick McHardy <kaber at trash.net>
Signed-off-by: Paul E. McKenney <paulmck at linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh at joshtriplett.org>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
include/linux/rculist.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index c92dd28..c9e7330 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -267,8 +267,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
*/
#define list_first_or_null_rcu(ptr, type, member) \
({struct list_head *__ptr = (ptr); \
- struct list_head __rcu *__next = list_next_rcu(__ptr); \
- likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \
+ struct list_head *__next = ACCESS_ONCE(__ptr->next); \
+ likely(__ptr != __next) ? \
+ list_entry_rcu(__next, type, member) : NULL; \
})
/**
--
1.8.1.2
More information about the kernel-team
mailing list