Blame view

lib/kobject_uevent.c 11.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
  #include <linux/string.h>
  #include <linux/kobject.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
20
21
  #include <linux/export.h>
  #include <linux/kmod.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
417daa1e8   Eric W. Biederman   hotplug: netns aw...
23
  #include <linux/user_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
  #include <linux/socket.h>
  #include <linux/skbuff.h>
  #include <linux/netlink.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  #include <net/sock.h>
07e98962f   Eric W. Biederman   kobject: Send hot...
28
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30

cd030c4cb   Cornelia Huck   kobject: fix link...
31
  u64 uevent_seqnum;
86d56134f   Michael Marineau   kobject: Make sup...
32
  #ifdef CONFIG_UEVENT_HELPER
6a8d8abb6   Kay Sievers   Driver core: add ...
33
  char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
86d56134f   Michael Marineau   kobject: Make sup...
34
  #endif
07e98962f   Eric W. Biederman   kobject: Send hot...
35
36
37
38
39
40
  #ifdef CONFIG_NET
  struct uevent_sock {
  	struct list_head list;
  	struct sock *sk;
  };
  static LIST_HEAD(uevent_sock_list);
cd030c4cb   Cornelia Huck   kobject: fix link...
41
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
42
43
  /* This lock protects uevent_seqnum and uevent_sock_list */
  static DEFINE_MUTEX(uevent_sock_mutex);
5c5daf657   Kay Sievers   Driver core: excl...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  /* 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...
68
69
  	if (count && (buf[count-1] == '
  ' || buf[count-1] == '\0'))
5c5daf657   Kay Sievers   Driver core: excl...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  		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...
87
  #ifdef CONFIG_NET
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
88
89
  static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
  {
82ef3d5d5   Weilong Chen   net: fix "queues"...
90
  	struct kobject *kobj = data, *ksobj;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
91
92
93
  	const struct kobj_ns_type_operations *ops;
  
  	ops = kobj_ns_ops(kobj);
82ef3d5d5   Weilong Chen   net: fix "queues"...
94
95
96
97
98
99
100
  	if (!ops && kobj->kset) {
  		ksobj = &kobj->kset->kobj;
  		if (ksobj->parent != NULL)
  			ops = kobj_ns_ops(ksobj->parent);
  	}
  
  	if (ops && ops->netlink_ns && kobj->ktype->namespace) {
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
101
102
103
104
105
106
107
108
  		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...
109
  #endif
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
110

86d56134f   Michael Marineau   kobject: Make sup...
111
  #ifdef CONFIG_UEVENT_HELPER
417daa1e8   Eric W. Biederman   hotplug: netns aw...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  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;
  }
bcccff93a   Vladimir Davydov   kobject: don't bl...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
  {
  	int len;
  
  	len = strlcpy(&env->buf[env->buflen], subsystem,
  		      sizeof(env->buf) - env->buflen);
  	if (len >= (sizeof(env->buf) - env->buflen)) {
  		WARN(1, KERN_ERR "init_uevent_argv: buffer size too small
  ");
  		return -ENOMEM;
  	}
  
  	env->argv[0] = uevent_helper;
  	env->argv[1] = &env->buf[env->buflen];
  	env->argv[2] = NULL;
  
  	env->buflen += len + 1;
  	return 0;
  }
  
  static void cleanup_uevent_env(struct subprocess_info *info)
  {
  	kfree(info->data);
  }
86d56134f   Michael Marineau   kobject: Make sup...
150
  #endif
bcccff93a   Vladimir Davydov   kobject: don't bl...
151

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
153
   * kobject_uevent_env - send an uevent with environmental data
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
   *
ccd490a3c   Kay Sievers   Driver core: kern...
155
   * @action: action that is happening
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
   * @kobj: struct kobject that the action is happening to
8a82472f8   Cornelia Huck   driver core: Intr...
157
   * @envp_ext: pointer to environmental data
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
158
   *
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
159
   * Returns 0 if kobject_uevent_env() is completed with success or the
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
160
   * corresponding error when it fails.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
162
  int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
7eff2e7a8   Kay Sievers   Driver core: chan...
163
  		       char *envp_ext[])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  {
7eff2e7a8   Kay Sievers   Driver core: chan...
165
166
  	struct kobj_uevent_env *env;
  	const char *action_string = kobject_actions[action];
5f123fbd8   Kay Sievers   [PATCH] merge kob...
167
168
169
170
  	const char *devpath = NULL;
  	const char *subsystem;
  	struct kobject *top_kobj;
  	struct kset *kset;
9cd43611c   Emese Revfy   kobject: Constify...
171
  	const struct kset_uevent_ops *uevent_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
  	int i = 0;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
173
  	int retval = 0;
07e98962f   Eric W. Biederman   kobject: Send hot...
174
175
176
  #ifdef CONFIG_NET
  	struct uevent_sock *ue_sk;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

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

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

542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
187
  	if (!top_kobj->kset) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
188
189
190
  		pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
  			 "without kset!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
191
  			 __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
192
193
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

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

f67f129e5   Ming Lei   Driver core: impl...
198
199
200
201
202
203
204
205
  	/* 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...
206
  	/* skip the event, if the filter returns zero. */
312c004d3   Kay Sievers   [PATCH] driver co...
207
  	if (uevent_ops && uevent_ops->filter)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
208
  		if (!uevent_ops->filter(kset, kobj)) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
209
210
211
  			pr_debug("kobject: '%s' (%p): %s: filter function "
  				 "caused the event to drop!
  ",
810304db7   Harvey Harrison   lib: replace rema...
212
  				 kobject_name(kobj), kobj, __func__);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
213
214
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215

864062457   Kay Sievers   driver core: fix ...
216
217
218
219
220
221
  	/* 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...
222
223
224
  		pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
  			 "event to drop!
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
225
  			 __func__);
864062457   Kay Sievers   driver core: fix ...
226
227
  		return 0;
  	}
7eff2e7a8   Kay Sievers   Driver core: chan...
228
229
230
  	/* environment buffer */
  	env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
  	if (!env)
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
231
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

5f123fbd8   Kay Sievers   [PATCH] merge kob...
233
234
  	/* complete object path */
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
235
236
  	if (!devpath) {
  		retval = -ENOENT;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
237
  		goto exit;
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
238
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239

5f123fbd8   Kay Sievers   [PATCH] merge kob...
240
  	/* default keys */
7eff2e7a8   Kay Sievers   Driver core: chan...
241
242
243
244
245
246
247
248
249
250
251
252
253
  	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...
254
  			retval = add_uevent_var(env, "%s", envp_ext[i]);
7eff2e7a8   Kay Sievers   Driver core: chan...
255
256
257
258
  			if (retval)
  				goto exit;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

5f123fbd8   Kay Sievers   [PATCH] merge kob...
260
  	/* let the kset specific function add its stuff */
312c004d3   Kay Sievers   [PATCH] driver co...
261
  	if (uevent_ops && uevent_ops->uevent) {
7eff2e7a8   Kay Sievers   Driver core: chan...
262
  		retval = uevent_ops->uevent(kset, kobj, env);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  		if (retval) {
9f66fa2a4   Greg Kroah-Hartman   kobject: clean up...
264
265
266
  			pr_debug("kobject: '%s' (%p): %s: uevent() returned "
  				 "%d
  ", kobject_name(kobj), kobj,
810304db7   Harvey Harrison   lib: replace rema...
267
  				 __func__, retval);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
  			goto exit;
  		}
  	}
0f4dafc05   Kay Sievers   Kobject: auto-cle...
271
272
273
274
275
276
277
278
279
280
  	/*
  	 * 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;
7b60a18da   Andrew Vagin   uevent: send even...
281
  	mutex_lock(&uevent_sock_mutex);
7eff2e7a8   Kay Sievers   Driver core: chan...
282
  	/* we will send an event, so request a new sequence number */
7b60a18da   Andrew Vagin   uevent: send even...
283
284
285
  	retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
  	if (retval) {
  		mutex_unlock(&uevent_sock_mutex);
7eff2e7a8   Kay Sievers   Driver core: chan...
286
  		goto exit;
7b60a18da   Andrew Vagin   uevent: send even...
287
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
289
  #if defined(CONFIG_NET)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
290
  	/* send netlink message */
07e98962f   Eric W. Biederman   kobject: Send hot...
291
292
  	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
  		struct sock *uevent_sock = ue_sk->sk;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
293
294
  		struct sk_buff *skb;
  		size_t len;
74099b18b   Kay Sievers   driver-core: skip...
295
296
  		if (!netlink_has_listeners(uevent_sock, 1))
  			continue;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
297
298
  		/* allocate message with the maximum possible size */
  		len = strlen(action_string) + strlen(devpath) + 2;
7eff2e7a8   Kay Sievers   Driver core: chan...
299
  		skb = alloc_skb(len + env->buflen, GFP_KERNEL);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
300
  		if (skb) {
7eff2e7a8   Kay Sievers   Driver core: chan...
301
  			char *scratch;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
302
303
304
305
306
  			/* 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...
307
308
  			for (i = 0; i < env->envp_idx; i++) {
  				len = strlen(env->envp[i]) + 1;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
309
  				scratch = skb_put(skb, len);
7eff2e7a8   Kay Sievers   Driver core: chan...
310
  				strcpy(scratch, env->envp[i]);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
311
312
313
  			}
  
  			NETLINK_CB(skb).dst_group = 1;
5f71a2962   Eric W. Biederman   kobj: Send hotplu...
314
315
316
317
  			retval = netlink_broadcast_filtered(uevent_sock, skb,
  							    0, 1, GFP_KERNEL,
  							    kobj_bcast_filter,
  							    kobj);
ff491a733   Pablo Neira Ayuso   netlink: change r...
318
  			/* ENOBUFS should be handled in userspace */
ebf4127cd   Milan Broz   kobj_uevent: Igno...
319
  			if (retval == -ENOBUFS || retval == -ESRCH)
ff491a733   Pablo Neira Ayuso   netlink: change r...
320
  				retval = 0;
e0d7bf5d5   Ming Lei   kobject: return t...
321
322
  		} else
  			retval = -ENOMEM;
5f123fbd8   Kay Sievers   [PATCH] merge kob...
323
  	}
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
324
  #endif
7b60a18da   Andrew Vagin   uevent: send even...
325
  	mutex_unlock(&uevent_sock_mutex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326

86d56134f   Michael Marineau   kobject: Make sup...
327
  #ifdef CONFIG_UEVENT_HELPER
5f123fbd8   Kay Sievers   [PATCH] merge kob...
328
  	/* call uevent_helper, usually only enabled during early boot */
417daa1e8   Eric W. Biederman   hotplug: netns aw...
329
  	if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
bcccff93a   Vladimir Davydov   kobject: don't bl...
330
  		struct subprocess_info *info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331

7eff2e7a8   Kay Sievers   Driver core: chan...
332
333
334
  		retval = add_uevent_var(env, "HOME=/");
  		if (retval)
  			goto exit;
e374a2bfe   Greg Kroah-Hartman   Kobject: fix codi...
335
336
  		retval = add_uevent_var(env,
  					"PATH=/sbin:/bin:/usr/sbin:/usr/bin");
7eff2e7a8   Kay Sievers   Driver core: chan...
337
338
  		if (retval)
  			goto exit;
bcccff93a   Vladimir Davydov   kobject: don't bl...
339
340
341
  		retval = init_uevent_argv(env, subsystem);
  		if (retval)
  			goto exit;
7eff2e7a8   Kay Sievers   Driver core: chan...
342

bcccff93a   Vladimir Davydov   kobject: don't bl...
343
344
345
346
347
348
349
350
  		retval = -ENOMEM;
  		info = call_usermodehelper_setup(env->argv[0], env->argv,
  						 env->envp, GFP_KERNEL,
  						 NULL, cleanup_uevent_env, env);
  		if (info) {
  			retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
  			env = NULL;	/* freed by cleanup_uevent_env */
  		}
5f123fbd8   Kay Sievers   [PATCH] merge kob...
351
  	}
86d56134f   Michael Marineau   kobject: Make sup...
352
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
  
  exit:
5f123fbd8   Kay Sievers   [PATCH] merge kob...
355
  	kfree(devpath);
7eff2e7a8   Kay Sievers   Driver core: chan...
356
  	kfree(env);
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
357
  	return retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
  }
8a82472f8   Cornelia Huck   driver core: Intr...
359
360
361
  EXPORT_SYMBOL_GPL(kobject_uevent_env);
  
  /**
f6e6e7799   Xiaotian Feng   kobject_uevent: f...
362
   * kobject_uevent - notify userspace by sending an uevent
8a82472f8   Cornelia Huck   driver core: Intr...
363
   *
ccd490a3c   Kay Sievers   Driver core: kern...
364
   * @action: action that is happening
8a82472f8   Cornelia Huck   driver core: Intr...
365
   * @kobj: struct kobject that the action is happening to
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
366
367
368
   *
   * Returns 0 if kobject_uevent() is completed with success or the
   * corresponding error when it fails.
8a82472f8   Cornelia Huck   driver core: Intr...
369
   */
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
370
  int kobject_uevent(struct kobject *kobj, enum kobject_action action)
8a82472f8   Cornelia Huck   driver core: Intr...
371
  {
542cfce6f   Aneesh Kumar K.V   kobject: kobject_...
372
  	return kobject_uevent_env(kobj, action, NULL);
8a82472f8   Cornelia Huck   driver core: Intr...
373
  }
312c004d3   Kay Sievers   [PATCH] driver co...
374
  EXPORT_SYMBOL_GPL(kobject_uevent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
  
  /**
7eff2e7a8   Kay Sievers   Driver core: chan...
377
378
379
   * 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
380
381
382
383
   *
   * Returns 0 if environment variable was added successfully or -ENOMEM
   * if no space was available.
   */
7eff2e7a8   Kay Sievers   Driver core: chan...
384
  int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
  {
  	va_list args;
7eff2e7a8   Kay Sievers   Driver core: chan...
387
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388

7eff2e7a8   Kay Sievers   Driver core: chan...
389
  	if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
390
391
  		WARN(1, KERN_ERR "add_uevent_var: too many keys
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
393
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
395
  
  	va_start(args, format);
7eff2e7a8   Kay Sievers   Driver core: chan...
396
397
398
  	len = vsnprintf(&env->buf[env->buflen],
  			sizeof(env->buf) - env->buflen,
  			format, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
399
  	va_end(args);
7eff2e7a8   Kay Sievers   Driver core: chan...
400
  	if (len >= (sizeof(env->buf) - env->buflen)) {
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
401
402
  		WARN(1, KERN_ERR "add_uevent_var: buffer size too small
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		return -ENOMEM;
7eff2e7a8   Kay Sievers   Driver core: chan...
404
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405

7eff2e7a8   Kay Sievers   Driver core: chan...
406
407
  	env->envp[env->envp_idx++] = &env->buf[env->buflen];
  	env->buflen += len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
  	return 0;
  }
312c004d3   Kay Sievers   [PATCH] driver co...
410
  EXPORT_SYMBOL_GPL(add_uevent_var);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411

4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
412
  #if defined(CONFIG_NET)
07e98962f   Eric W. Biederman   kobject: Send hot...
413
  static int uevent_net_init(struct net *net)
5f123fbd8   Kay Sievers   [PATCH] merge kob...
414
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
415
  	struct uevent_sock *ue_sk;
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
416
417
  	struct netlink_kernel_cfg cfg = {
  		.groups	= 1,
9785e10ae   Pablo Neira Ayuso   netlink: kill net...
418
  		.flags	= NL_CFG_F_NONROOT_RECV,
a31f2d17b   Pablo Neira Ayuso   netlink: add netl...
419
  	};
07e98962f   Eric W. Biederman   kobject: Send hot...
420
421
422
423
  
  	ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
  	if (!ue_sk)
  		return -ENOMEM;
9f00d9776   Pablo Neira Ayuso   netlink: hide str...
424
  	ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
07e98962f   Eric W. Biederman   kobject: Send hot...
425
  	if (!ue_sk->sk) {
5f123fbd8   Kay Sievers   [PATCH] merge kob...
426
427
428
  		printk(KERN_ERR
  		       "kobject_uevent: unable to create netlink socket!
  ");
743db2d90   Dan Carpenter   kobject: free mem...
429
  		kfree(ue_sk);
5f123fbd8   Kay Sievers   [PATCH] merge kob...
430
431
  		return -ENODEV;
  	}
07e98962f   Eric W. Biederman   kobject: Send hot...
432
433
434
  	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...
435
436
  	return 0;
  }
07e98962f   Eric W. Biederman   kobject: Send hot...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  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)
  {
07e98962f   Eric W. Biederman   kobject: Send hot...
464
465
  	return register_pernet_subsys(&uevent_net_ops);
  }
5f123fbd8   Kay Sievers   [PATCH] merge kob...
466
  postcore_initcall(kobject_uevent_init);
4d17ffda3   Kay Sievers   [PATCH] Kobject: ...
467
  #endif