aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Vagin <avagin@openvz.org>2012-03-07 05:49:56 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-03-08 15:56:40 -0500
commit7b60a18da393ed70db043a777fd9e6d5363077c4 (patch)
treecf83f1b5fdd5b7fab96c256f40db877112b277fe
parent8b0372a258e6bd0e9e5ea3f3d5f05a6bf3972fee (diff)
uevent: send events in correct order according to seqnum (v3)
The queue handling in the udev daemon assumes that the events are ordered. Before this patch uevent_seqnum is incremented under sequence_lock, than an event is send uner uevent_sock_mutex. I want to say that code contained a window between incrementing seqnum and sending an event. This patch locks uevent_sock_mutex before incrementing uevent_seqnum. v2: delete sequence_lock, uevent_seqnum is protected by uevent_sock_mutex v3: unlock the mutex before the goto exit Thanks for Kay for the comments. Signed-off-by: Andrew Vagin <avagin@openvz.org> Tested-By: Kay Sievers <kay.sievers@vrfy.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--lib/kobject_uevent.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index e66e9b632617..75cbdb52bf5c 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -29,16 +29,17 @@
29 29
30u64 uevent_seqnum; 30u64 uevent_seqnum;
31char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; 31char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
32static DEFINE_SPINLOCK(sequence_lock);
33#ifdef CONFIG_NET 32#ifdef CONFIG_NET
34struct uevent_sock { 33struct uevent_sock {
35 struct list_head list; 34 struct list_head list;
36 struct sock *sk; 35 struct sock *sk;
37}; 36};
38static LIST_HEAD(uevent_sock_list); 37static LIST_HEAD(uevent_sock_list);
39static DEFINE_MUTEX(uevent_sock_mutex);
40#endif 38#endif
41 39
40/* This lock protects uevent_seqnum and uevent_sock_list */
41static DEFINE_MUTEX(uevent_sock_mutex);
42
42/* the strings here must match the enum in include/linux/kobject.h */ 43/* the strings here must match the enum in include/linux/kobject.h */
43static const char *kobject_actions[] = { 44static const char *kobject_actions[] = {
44 [KOBJ_ADD] = "add", 45 [KOBJ_ADD] = "add",
@@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
136 struct kobject *top_kobj; 137 struct kobject *top_kobj;
137 struct kset *kset; 138 struct kset *kset;
138 const struct kset_uevent_ops *uevent_ops; 139 const struct kset_uevent_ops *uevent_ops;
139 u64 seq;
140 int i = 0; 140 int i = 0;
141 int retval = 0; 141 int retval = 0;
142#ifdef CONFIG_NET 142#ifdef CONFIG_NET
@@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
243 else if (action == KOBJ_REMOVE) 243 else if (action == KOBJ_REMOVE)
244 kobj->state_remove_uevent_sent = 1; 244 kobj->state_remove_uevent_sent = 1;
245 245
246 mutex_lock(&uevent_sock_mutex);
246 /* we will send an event, so request a new sequence number */ 247 /* we will send an event, so request a new sequence number */
247 spin_lock(&sequence_lock); 248 retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
248 seq = ++uevent_seqnum; 249 if (retval) {
249 spin_unlock(&sequence_lock); 250 mutex_unlock(&uevent_sock_mutex);
250 retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
251 if (retval)
252 goto exit; 251 goto exit;
252 }
253 253
254#if defined(CONFIG_NET) 254#if defined(CONFIG_NET)
255 /* send netlink message */ 255 /* send netlink message */
256 mutex_lock(&uevent_sock_mutex);
257 list_for_each_entry(ue_sk, &uevent_sock_list, list) { 256 list_for_each_entry(ue_sk, &uevent_sock_list, list) {
258 struct sock *uevent_sock = ue_sk->sk; 257 struct sock *uevent_sock = ue_sk->sk;
259 struct sk_buff *skb; 258 struct sk_buff *skb;
@@ -290,8 +289,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
290 } else 289 } else
291 retval = -ENOMEM; 290 retval = -ENOMEM;
292 } 291 }
293 mutex_unlock(&uevent_sock_mutex);
294#endif 292#endif
293 mutex_unlock(&uevent_sock_mutex);
295 294
296 /* call uevent_helper, usually only enabled during early boot */ 295 /* call uevent_helper, usually only enabled during early boot */
297 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { 296 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {