Blame view

lib/kobject_uevent.c 10.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * kernel userspace event delivery
   *
   * Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
   * Copyright (C) 2004 Novell, Inc.  All rights reserved.
   * Copyright (C) 2004 IBM, Inc. All rights reserved.
   *
   * Licensed under the GNU GPL v2.
   *
   * Authors:
   *	Robert Love		<rml@novell.com>
   *	Kay Sievers		<kay.sievers@vrfy.org>
   *	Arjan van de Ven	<arjanv@redhat.com>
   *	Greg Kroah-Hartman	<greg@kroah.com>
   */
  
  #include <linux/spinlock.h>
2d38f9a4f   Denis V. Lunev   [NETNS]: Do no in...
18
19
20
  #include <linux/string.h>
  #include <linux/kobject.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
21
  #include <linux/slab.h>
417daa1e8   Eric W. Biederman   hotplug: netns aw...
22
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  #include <linux/socket.h>
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <net/sock.h>
07e98962f   Eric W. Biederman   kobject: Send hot...
27
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

cd030c4cb   Cornelia Huck   kobject: fix link...
30
  u64 uevent_seqnum;
6a8d8abb6   Kay Sievers   Driver core: add ...
31
  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
cd030c4cb   Cornelia Huck   kobject: fix link...
32
  static DEFINE_SPINLOCK(sequence_lock);
07e98962f   Eric W. Biederman   kobject: Send hot...
33
34
35
36
37
38
39
  #ifdef CONFIG_NET
  struct uevent_sock {
  	struct list_head list;
  	struct sock *sk;
  };
  static LIST_HEAD(uevent_sock_list);
  static DEFINE_MUTEX(uevent_sock_mutex);
cd030c4cb   Cornelia Huck   kobject: fix link...
40
  #endif
5c5daf657   Kay Sievers   Driver core: excl...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  /* the strings here must match the enum in include/linux/kobject.h */
  static const char *kobject_actions[] = {
  	[KOBJ_ADD] =		"add",
  	[KOBJ_REMOVE] =		"remove",
  	[KOBJ_CHANGE] =		"change",
  	[KOBJ_MOVE] =		"move",
  	[KOBJ_ONLINE] =		"online",
  	[KOBJ_OFFLINE] =	"offline",
  };
  
  /**
   * kobject_action_type - translate action string to numeric type
   *
   * @buf: buffer containing the action string, newline is ignored
   * @len: length of buffer
   * @type: pointer to the location to store the action type
   *
   * Returns 0 if the action string was recognized.
   */
  int kobject_action_type(const char *buf, size_t count,
  			enum kobject_action *type)
  {
  	enum kobject_action action;
  	int ret = -EINVAL;
a9edadbf7   Mark Lord   fix uevent action...
65
66
  	if (count && (buf[count-1] == '
  ' || buf[count-1] == '\0'))
5c5daf657   Kay Sievers   Driver core: excl...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
  		count--;
  
  	if (!count)
  		goto out;
  
  	for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
  		if (strncmp(kobject_actions[action], buf, count) != 0)
  			continue;
  		if (kobject_actions[action][count] != '\0')
  			continue;
  		*type = action;
  		ret = 0;
  		break;
  	}
  out:
  	return ret;
  }
c84212860   Andrew Morton   lib/kobject_ueven...
84
  #ifdef CONFIG_NET
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
  {
  	struct kobject *kobj = data;
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
  	if (ops) {
  		const void *sock_ns, *ns;
  		ns = kobj->ktype->namespace(kobj);
  		sock_ns = ops->netlink_ns(dsk);
  		return sock_ns != ns;
  	}
  
  	return 0;
  }
c84212860   Andrew Morton   lib/kobject_ueven...
100
  #endif
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
101

417daa1e8   Eric W. Biederman   hotplug: netns aw...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  static int kobj_usermode_filter(struct kobject *kobj)
  {
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
  	if (ops) {
  		const void *init_ns, *ns;
  		ns = kobj->ktype->namespace(kobj);
  		init_ns = ops->initial_ns();
  		return ns != init_ns;
  	}
  
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
117
   * kobject_uevent_env - send an uevent with environmental data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
   *
ccd490a3c   Kay Sievers   Driver core: kern...
119
   * @action: action that is happening
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
   * @kobj: struct kobject that the action is happening to
8a82472f8   Cornelia Huck   driver core: Intr...
121
   * @envp_ext: pointer to environmental data
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
122
   *
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
123
   * Returns 0 if kobject_uevent_env() is completed with success or the
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
124
   * corresponding error when it fails.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
126
  int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
7eff2e7a8   Kay Sievers   Driver core: chan...
127
  		       char *envp_ext[])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
129
130
  	struct kobj_uevent_env *env;
  	const char *action_string = kobject_actions[action];
5f123fbd8   Kay Sievers   [PATCH] merge kob...
131
132
133
134
  	const char *devpath = NULL;
  	const char *subsystem;
  	struct kobject *top_kobj;
  	struct kset *kset;
9cd43611c   Emese Revfy   kobject: Constify...
135
  	const struct kset_uevent_ops *uevent_ops;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
136
  	u64 seq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  	int i = 0;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
138
  	int retval = 0;
07e98962f   Eric W. Biederman   kobject: Send hot...
139
140
141
  #ifdef CONFIG_NET
  	struct uevent_sock *ue_sk;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142

9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
143
144
  	pr_debug("kobject: '%s' (%p): %s
  ",
810304db7   Harvey Harrison   lib: replace rema...
145
  		 kobject_name(kobj), kobj, __func__);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
146

5f123fbd8   Kay Sievers   [PATCH] merge kob...
147
148
  	/* search the kset we belong to */
  	top_kobj = kobj;
ccd490a3c   Kay Sievers   Driver core: kern...
149
  	while (!top_kobj->kset && top_kobj->parent)
14193fb91   John Anthony Kazos Jr   Kobject: kobject_...
150
  		top_kobj = top_kobj->parent;
ccd490a3c   Kay Sievers   Driver core: kern...
151

542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
152
  	if (!top_kobj->kset) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
153
154
155
  		pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
  			 "without kset!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
156
  			 __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
157
158
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159

5f123fbd8   Kay Sievers   [PATCH] merge kob...
160
  	kset = top_kobj->kset;
312c004d3   Kay Sievers   [PATCH] driver co...
161
  	uevent_ops = kset->uevent_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

f67f129e5   Ming Lei   Driver core: impl...
163
164
165
166
167
168
169
170
  	/* skip the event, if uevent_suppress is set*/
  	if (kobj->uevent_suppress) {
  		pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
  				 "caused the event to drop!
  ",
  				 kobject_name(kobj), kobj, __func__);
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
171
  	/* skip the event, if the filter returns zero. */
312c004d3   Kay Sievers   [PATCH] driver co...
172
  	if (uevent_ops && uevent_ops->filter)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
173
  		if (!uevent_ops->filter(kset, kobj)) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
174
175
176
  			pr_debug("kobject: '%s' (%p): %s: filter function "
  				 "caused the event to drop!
  ",
810304db7   Harvey Harrison   lib: replace rema...
177
  				 kobject_name(kobj), kobj, __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
178
179
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180

864062457   Kay Sievers   driver core: fix ...
181
182
183
184
185
186
  	/* originating subsystem */
  	if (uevent_ops && uevent_ops->name)
  		subsystem = uevent_ops->name(kset, kobj);
  	else
  		subsystem = kobject_name(&kset->kobj);
  	if (!subsystem) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
187
188
189
  		pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
  			 "event to drop!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
190
  			 __func__);
864062457   Kay Sievers   driver core: fix ...
191
192
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
193
194
195
  	/* environment buffer */
  	env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
  	if (!env)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
196
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

5f123fbd8   Kay Sievers   [PATCH] merge kob...
198
199
  	/* complete object path */
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
200
201
  	if (!devpath) {
  		retval = -ENOENT;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
202
  		goto exit;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
203
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

5f123fbd8   Kay Sievers   [PATCH] merge kob...
205
  	/* default keys */
7eff2e7a8   Kay Sievers   Driver core: chan...
206
207
208
209
210
211
212
213
214
215
216
217
218
  	retval = add_uevent_var(env, "ACTION=%s", action_string);
  	if (retval)
  		goto exit;
  	retval = add_uevent_var(env, "DEVPATH=%s", devpath);
  	if (retval)
  		goto exit;
  	retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
  	if (retval)
  		goto exit;
  
  	/* keys passed in from the caller */
  	if (envp_ext) {
  		for (i = 0; envp_ext[i]; i++) {
c65b9145f   Tejun Heo   uevent: don't pas...
219
  			retval = add_uevent_var(env, "%s", envp_ext[i]);
7eff2e7a8   Kay Sievers   Driver core: chan...
220
221
222
223
  			if (retval)
  				goto exit;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224

5f123fbd8   Kay Sievers   [PATCH] merge kob...
225
  	/* let the kset specific function add its stuff */
312c004d3   Kay Sievers   [PATCH] driver co...
226
  	if (uevent_ops && uevent_ops->uevent) {
7eff2e7a8   Kay Sievers   Driver core: chan...
227
  		retval = uevent_ops->uevent(kset, kobj, env);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		if (retval) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
229
230
231
  			pr_debug("kobject: '%s' (%p): %s: uevent() returned "
  				 "%d
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
232
  				 __func__, retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
  			goto exit;
  		}
  	}
0f4dafc05   Kay Sievers   Kobject: auto-cle...
236
237
238
239
240
241
242
243
244
245
  	/*
  	 * Mark "add" and "remove" events in the object to ensure proper
  	 * events to userspace during automatic cleanup. If the object did
  	 * send an "add" event, "remove" will automatically generated by
  	 * the core, if not already done by the caller.
  	 */
  	if (action == KOBJ_ADD)
  		kobj->state_add_uevent_sent = 1;
  	else if (action == KOBJ_REMOVE)
  		kobj->state_remove_uevent_sent = 1;
7eff2e7a8   Kay Sievers   Driver core: chan...
246
  	/* we will send an event, so request a new sequence number */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
  	spin_lock(&sequence_lock);
312c004d3   Kay Sievers   [PATCH] driver co...
248
  	seq = ++uevent_seqnum;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  	spin_unlock(&sequence_lock);
7eff2e7a8   Kay Sievers   Driver core: chan...
250
251
252
  	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
  	if (retval)
  		goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
254
  #if defined(CONFIG_NET)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
255
  	/* send netlink message */
07e98962f   Eric W. Biederman   kobject: Send hot...
256
257
258
  	mutex_lock(&uevent_sock_mutex);
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		struct sock *uevent_sock = ue_sk->sk;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
259
260
  		struct sk_buff *skb;
  		size_t len;
74099b18b   Kay Sievers   driver-core: skip...
261
262
  		if (!netlink_has_listeners(uevent_sock, 1))
  			continue;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
263
264
  		/* allocate message with the maximum possible size */
  		len = strlen(action_string) + strlen(devpath) + 2;
7eff2e7a8   Kay Sievers   Driver core: chan...
265
  		skb = alloc_skb(len + env->buflen, GFP_KERNEL);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
266
  		if (skb) {
7eff2e7a8   Kay Sievers   Driver core: chan...
267
  			char *scratch;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
268
269
270
271
272
  			/* add header */
  			scratch = skb_put(skb, len);
  			sprintf(scratch, "%s@%s", action_string, devpath);
  
  			/* copy keys to our continuous event payload buffer */
7eff2e7a8   Kay Sievers   Driver core: chan...
273
274
  			for (i = 0; i < env->envp_idx; i++) {
  				len = strlen(env->envp[i]) + 1;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
275
  				scratch = skb_put(skb, len);
7eff2e7a8   Kay Sievers   Driver core: chan...
276
  				strcpy(scratch, env->envp[i]);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
277
278
279
  			}
  
  			NETLINK_CB(skb).dst_group = 1;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
280
281
282
283
  			retval = netlink_broadcast_filtered(uevent_sock, skb,
  							    0, 1, GFP_KERNEL,
  							    kobj_bcast_filter,
  							    kobj);
ff491a733   Pablo Neira Ayuso   netlink: change r...
284
  			/* ENOBUFS should be handled in userspace */
ebf4127cd   Milan Broz   kobj_uevent: Igno...
285
  			if (retval == -ENOBUFS || retval == -ESRCH)
ff491a733   Pablo Neira Ayuso   netlink: change r...
286
  				retval = 0;
e0d7bf5d5   Ming Lei   kobject: return t...
287
288
  		} else
  			retval = -ENOMEM;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
289
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
290
  	mutex_unlock(&uevent_sock_mutex);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
291
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

5f123fbd8   Kay Sievers   [PATCH] merge kob...
293
  	/* call uevent_helper, usually only enabled during early boot */
417daa1e8   Eric W. Biederman   hotplug: netns aw...
294
  	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
295
  		char *argv [3];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296

312c004d3   Kay Sievers   [PATCH] driver co...
297
  		argv [0] = uevent_helper;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
298
299
  		argv [1] = (char *)subsystem;
  		argv [2] = NULL;
7eff2e7a8   Kay Sievers   Driver core: chan...
300
301
302
  		retval = add_uevent_var(env, "HOME=/");
  		if (retval)
  			goto exit;
e374a2bfe   Greg Kroah-Hartman   Kobject: fix codi...
303
304
  		retval = add_uevent_var(env,
  					"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
7eff2e7a8   Kay Sievers   Driver core: chan...
305
306
  		if (retval)
  			goto exit;
0ad1d6f37   Wang Chen   kobject: Transmit...
307
  		retval = call_usermodehelper(argv[0], argv,
05f54c13c   Hugh Dickins   Revert "kobject: ...
308
  					     env->envp, UMH_WAIT_EXEC);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
309
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  
  exit:
5f123fbd8   Kay Sievers   [PATCH] merge kob...
312
  	kfree(devpath);
7eff2e7a8   Kay Sievers   Driver core: chan...
313
  	kfree(env);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
314
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  }
8a82472f8   Cornelia Huck   driver core: Intr...
316
317
318
  EXPORT_SYMBOL_GPL(kobject_uevent_env);
  
  /**
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
319
   * kobject_uevent - notify userspace by sending an uevent
8a82472f8   Cornelia Huck   driver core: Intr...
320
   *
ccd490a3c   Kay Sievers   Driver core: kern...
321
   * @action: action that is happening
8a82472f8   Cornelia Huck   driver core: Intr...
322
   * @kobj: struct kobject that the action is happening to
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
323
324
325
   *
   * Returns 0 if kobject_uevent() is completed with success or the
   * corresponding error when it fails.
8a82472f8   Cornelia Huck   driver core: Intr...
326
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
327
  int kobject_uevent(struct kobject *kobj, enum kobject_action action)
8a82472f8   Cornelia Huck   driver core: Intr...
328
  {
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
329
  	return kobject_uevent_env(kobj, action, NULL);
8a82472f8   Cornelia Huck   driver core: Intr...
330
  }
312c004d3   Kay Sievers   [PATCH] driver co...
331
  EXPORT_SYMBOL_GPL(kobject_uevent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
  
  /**
7eff2e7a8   Kay Sievers   Driver core: chan...
334
335
336
   * add_uevent_var - add key value string to the environment buffer
   * @env: environment buffer structure
   * @format: printf format for the key=value pair
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
340
   *
   * Returns 0 if environment variable was added successfully or -ENOMEM
   * if no space was available.
   */
7eff2e7a8   Kay Sievers   Driver core: chan...
341
  int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  {
  	va_list args;
7eff2e7a8   Kay Sievers   Driver core: chan...
344
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345

7eff2e7a8   Kay Sievers   Driver core: chan...
346
  	if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
347
348
  		WARN(1, KERN_ERR "add_uevent_var: too many keys
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
350
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
  
  	va_start(args, format);
7eff2e7a8   Kay Sievers   Driver core: chan...
353
354
355
  	len = vsnprintf(&env->buf[env->buflen],
  			sizeof(env->buf) - env->buflen,
  			format, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  	va_end(args);
7eff2e7a8   Kay Sievers   Driver core: chan...
357
  	if (len >= (sizeof(env->buf) - env->buflen)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
358
359
  		WARN(1, KERN_ERR "add_uevent_var: buffer size too small
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
361
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362

7eff2e7a8   Kay Sievers   Driver core: chan...
363
364
  	env->envp[env->envp_idx++] = &env->buf[env->buflen];
  	env->buflen += len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
  	return 0;
  }
312c004d3   Kay Sievers   [PATCH] driver co...
367
  EXPORT_SYMBOL_GPL(add_uevent_var);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
369
  #if defined(CONFIG_NET)
07e98962f   Eric W. Biederman   kobject: Send hot...
370
  static int uevent_net_init(struct net *net)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
371
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
372
373
374
375
376
377
378
379
380
  	struct uevent_sock *ue_sk;
  
  	ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
  	if (!ue_sk)
  		return -ENOMEM;
  
  	ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
  					  1, NULL, NULL, THIS_MODULE);
  	if (!ue_sk->sk) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
381
382
383
  		printk(KERN_ERR
  		       "kobject_uevent: unable to create netlink socket!
  ");
743db2d90   Dan Carpenter   kobject: free mem...
384
  		kfree(ue_sk);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
385
386
  		return -ENODEV;
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
387
388
389
  	mutex_lock(&uevent_sock_mutex);
  	list_add_tail(&ue_sk->list, &uevent_sock_list);
  	mutex_unlock(&uevent_sock_mutex);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
390
391
  	return 0;
  }
07e98962f   Eric W. Biederman   kobject: Send hot...
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  static void uevent_net_exit(struct net *net)
  {
  	struct uevent_sock *ue_sk;
  
  	mutex_lock(&uevent_sock_mutex);
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		if (sock_net(ue_sk->sk) == net)
  			goto found;
  	}
  	mutex_unlock(&uevent_sock_mutex);
  	return;
  
  found:
  	list_del(&ue_sk->list);
  	mutex_unlock(&uevent_sock_mutex);
  
  	netlink_kernel_release(ue_sk->sk);
  	kfree(ue_sk);
  }
  
  static struct pernet_operations uevent_net_ops = {
  	.init	= uevent_net_init,
  	.exit	= uevent_net_exit,
  };
  
  static int __init kobject_uevent_init(void)
  {
  	netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
  	return register_pernet_subsys(&uevent_net_ops);
  }
5f123fbd8   Kay Sievers   [PATCH] merge kob...
422
  postcore_initcall(kobject_uevent_init);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
423
  #endif