|
24 | 24 | #include <linux/skbuff.h>
|
25 | 25 | #include <linux/netlink.h>
|
26 | 26 | #include <net/sock.h>
|
| 27 | +#include <net/net_namespace.h> |
27 | 28 |
|
28 | 29 |
|
29 | 30 | u64 uevent_seqnum;
|
30 | 31 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
31 | 32 | static DEFINE_SPINLOCK(sequence_lock);
|
32 |
| -#if defined(CONFIG_NET) |
33 |
| -static struct sock *uevent_sock; |
| 33 | +#ifdef CONFIG_NET |
| 34 | +struct uevent_sock { |
| 35 | + struct list_head list; |
| 36 | + struct sock *sk; |
| 37 | +}; |
| 38 | +static LIST_HEAD(uevent_sock_list); |
| 39 | +static DEFINE_MUTEX(uevent_sock_mutex); |
34 | 40 | #endif
|
35 | 41 |
|
36 | 42 | /* the strings here must match the enum in include/linux/kobject.h */
|
@@ -100,6 +106,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
100 | 106 | u64 seq;
|
101 | 107 | int i = 0;
|
102 | 108 | int retval = 0;
|
| 109 | +#ifdef CONFIG_NET |
| 110 | + struct uevent_sock *ue_sk; |
| 111 | +#endif |
103 | 112 |
|
104 | 113 | pr_debug("kobject: '%s' (%p): %s\n",
|
105 | 114 | kobject_name(kobj), kobj, __func__);
|
@@ -211,7 +220,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
211 | 220 |
|
212 | 221 | #if defined(CONFIG_NET)
|
213 | 222 | /* send netlink message */
|
214 |
| - if (uevent_sock) { |
| 223 | + mutex_lock(&uevent_sock_mutex); |
| 224 | + list_for_each_entry(ue_sk, &uevent_sock_list, list) { |
| 225 | + struct sock *uevent_sock = ue_sk->sk; |
215 | 226 | struct sk_buff *skb;
|
216 | 227 | size_t len;
|
217 | 228 |
|
@@ -241,6 +252,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
241 | 252 | } else
|
242 | 253 | retval = -ENOMEM;
|
243 | 254 | }
|
| 255 | + mutex_unlock(&uevent_sock_mutex); |
244 | 256 | #endif
|
245 | 257 |
|
246 | 258 | /* call uevent_helper, usually only enabled during early boot */
|
@@ -320,18 +332,58 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
|
320 | 332 | EXPORT_SYMBOL_GPL(add_uevent_var);
|
321 | 333 |
|
322 | 334 | #if defined(CONFIG_NET)
|
323 |
| -static int __init kobject_uevent_init(void) |
| 335 | +static int uevent_net_init(struct net *net) |
324 | 336 | {
|
325 |
| - uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, |
326 |
| - 1, NULL, NULL, THIS_MODULE); |
327 |
| - if (!uevent_sock) { |
| 337 | + struct uevent_sock *ue_sk; |
| 338 | + |
| 339 | + ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL); |
| 340 | + if (!ue_sk) |
| 341 | + return -ENOMEM; |
| 342 | + |
| 343 | + ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, |
| 344 | + 1, NULL, NULL, THIS_MODULE); |
| 345 | + if (!ue_sk->sk) { |
328 | 346 | printk(KERN_ERR
|
329 | 347 | "kobject_uevent: unable to create netlink socket!\n");
|
330 | 348 | return -ENODEV;
|
331 | 349 | }
|
332 |
| - netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); |
| 350 | + mutex_lock(&uevent_sock_mutex); |
| 351 | + list_add_tail(&ue_sk->list, &uevent_sock_list); |
| 352 | + mutex_unlock(&uevent_sock_mutex); |
333 | 353 | return 0;
|
334 | 354 | }
|
335 | 355 |
|
| 356 | +static void uevent_net_exit(struct net *net) |
| 357 | +{ |
| 358 | + struct uevent_sock *ue_sk; |
| 359 | + |
| 360 | + mutex_lock(&uevent_sock_mutex); |
| 361 | + list_for_each_entry(ue_sk, &uevent_sock_list, list) { |
| 362 | + if (sock_net(ue_sk->sk) == net) |
| 363 | + goto found; |
| 364 | + } |
| 365 | + mutex_unlock(&uevent_sock_mutex); |
| 366 | + return; |
| 367 | + |
| 368 | +found: |
| 369 | + list_del(&ue_sk->list); |
| 370 | + mutex_unlock(&uevent_sock_mutex); |
| 371 | + |
| 372 | + netlink_kernel_release(ue_sk->sk); |
| 373 | + kfree(ue_sk); |
| 374 | +} |
| 375 | + |
| 376 | +static struct pernet_operations uevent_net_ops = { |
| 377 | + .init = uevent_net_init, |
| 378 | + .exit = uevent_net_exit, |
| 379 | +}; |
| 380 | + |
| 381 | +static int __init kobject_uevent_init(void) |
| 382 | +{ |
| 383 | + netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); |
| 384 | + return register_pernet_subsys(&uevent_net_ops); |
| 385 | +} |
| 386 | + |
| 387 | + |
336 | 388 | postcore_initcall(kobject_uevent_init);
|
337 | 389 | #endif
|
0 commit comments