Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
kobject_uevent.c
Go to the documentation of this file.
1 /*
2  * kernel userspace event delivery
3  *
4  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2004 Novell, Inc. All rights reserved.
6  * Copyright (C) 2004 IBM, Inc. All rights reserved.
7  *
8  * Licensed under the GNU GPL v2.
9  *
10  * Authors:
11  * Robert Love <[email protected]>
12  * Kay Sievers <[email protected]>
13  * Arjan van de Ven <[email protected]>
14  * Greg Kroah-Hartman <[email protected]>
15  */
16 
17 #include <linux/spinlock.h>
18 #include <linux/string.h>
19 #include <linux/kobject.h>
20 #include <linux/export.h>
21 #include <linux/kmod.h>
22 #include <linux/slab.h>
23 #include <linux/user_namespace.h>
24 #include <linux/socket.h>
25 #include <linux/skbuff.h>
26 #include <linux/netlink.h>
27 #include <net/sock.h>
28 #include <net/net_namespace.h>
29 
30 
32 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
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 #endif
40 
41 /* This lock protects uevent_seqnum and uevent_sock_list */
42 static DEFINE_MUTEX(uevent_sock_mutex);
43 
44 /* the strings here must match the enum in include/linux/kobject.h */
45 static const char *kobject_actions[] = {
46  [KOBJ_ADD] = "add",
47  [KOBJ_REMOVE] = "remove",
48  [KOBJ_CHANGE] = "change",
49  [KOBJ_MOVE] = "move",
50  [KOBJ_ONLINE] = "online",
51  [KOBJ_OFFLINE] = "offline",
52 };
53 
63 int kobject_action_type(const char *buf, size_t count,
64  enum kobject_action *type)
65 {
67  int ret = -EINVAL;
68 
69  if (count && (buf[count-1] == '\n' || buf[count-1] == '\0'))
70  count--;
71 
72  if (!count)
73  goto out;
74 
75  for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
76  if (strncmp(kobject_actions[action], buf, count) != 0)
77  continue;
78  if (kobject_actions[action][count] != '\0')
79  continue;
80  *type = action;
81  ret = 0;
82  break;
83  }
84 out:
85  return ret;
86 }
87 
88 #ifdef CONFIG_NET
89 static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
90 {
91  struct kobject *kobj = data;
92  const struct kobj_ns_type_operations *ops;
93 
94  ops = kobj_ns_ops(kobj);
95  if (ops) {
96  const void *sock_ns, *ns;
97  ns = kobj->ktype->namespace(kobj);
98  sock_ns = ops->netlink_ns(dsk);
99  return sock_ns != ns;
100  }
101 
102  return 0;
103 }
104 #endif
105 
106 static int kobj_usermode_filter(struct kobject *kobj)
107 {
108  const struct kobj_ns_type_operations *ops;
109 
110  ops = kobj_ns_ops(kobj);
111  if (ops) {
112  const void *init_ns, *ns;
113  ns = kobj->ktype->namespace(kobj);
114  init_ns = ops->initial_ns();
115  return ns != init_ns;
116  }
117 
118  return 0;
119 }
120 
132  char *envp_ext[])
133 {
134  struct kobj_uevent_env *env;
135  const char *action_string = kobject_actions[action];
136  const char *devpath = NULL;
137  const char *subsystem;
138  struct kobject *top_kobj;
139  struct kset *kset;
140  const struct kset_uevent_ops *uevent_ops;
141  int i = 0;
142  int retval = 0;
143 #ifdef CONFIG_NET
144  struct uevent_sock *ue_sk;
145 #endif
146 
147  pr_debug("kobject: '%s' (%p): %s\n",
148  kobject_name(kobj), kobj, __func__);
149 
150  /* search the kset we belong to */
151  top_kobj = kobj;
152  while (!top_kobj->kset && top_kobj->parent)
153  top_kobj = top_kobj->parent;
154 
155  if (!top_kobj->kset) {
156  pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
157  "without kset!\n", kobject_name(kobj), kobj,
158  __func__);
159  return -EINVAL;
160  }
161 
162  kset = top_kobj->kset;
163  uevent_ops = kset->uevent_ops;
164 
165  /* skip the event, if uevent_suppress is set*/
166  if (kobj->uevent_suppress) {
167  pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
168  "caused the event to drop!\n",
169  kobject_name(kobj), kobj, __func__);
170  return 0;
171  }
172  /* skip the event, if the filter returns zero. */
173  if (uevent_ops && uevent_ops->filter)
174  if (!uevent_ops->filter(kset, kobj)) {
175  pr_debug("kobject: '%s' (%p): %s: filter function "
176  "caused the event to drop!\n",
177  kobject_name(kobj), kobj, __func__);
178  return 0;
179  }
180 
181  /* originating subsystem */
182  if (uevent_ops && uevent_ops->name)
183  subsystem = uevent_ops->name(kset, kobj);
184  else
185  subsystem = kobject_name(&kset->kobj);
186  if (!subsystem) {
187  pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
188  "event to drop!\n", kobject_name(kobj), kobj,
189  __func__);
190  return 0;
191  }
192 
193  /* environment buffer */
194  env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
195  if (!env)
196  return -ENOMEM;
197 
198  /* complete object path */
199  devpath = kobject_get_path(kobj, GFP_KERNEL);
200  if (!devpath) {
201  retval = -ENOENT;
202  goto exit;
203  }
204 
205  /* default keys */
206  retval = add_uevent_var(env, "ACTION=%s", action_string);
207  if (retval)
208  goto exit;
209  retval = add_uevent_var(env, "DEVPATH=%s", devpath);
210  if (retval)
211  goto exit;
212  retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
213  if (retval)
214  goto exit;
215 
216  /* keys passed in from the caller */
217  if (envp_ext) {
218  for (i = 0; envp_ext[i]; i++) {
219  retval = add_uevent_var(env, "%s", envp_ext[i]);
220  if (retval)
221  goto exit;
222  }
223  }
224 
225  /* let the kset specific function add its stuff */
226  if (uevent_ops && uevent_ops->uevent) {
227  retval = uevent_ops->uevent(kset, kobj, env);
228  if (retval) {
229  pr_debug("kobject: '%s' (%p): %s: uevent() returned "
230  "%d\n", kobject_name(kobj), kobj,
231  __func__, retval);
232  goto exit;
233  }
234  }
235 
236  /*
237  * Mark "add" and "remove" events in the object to ensure proper
238  * events to userspace during automatic cleanup. If the object did
239  * send an "add" event, "remove" will automatically generated by
240  * the core, if not already done by the caller.
241  */
242  if (action == KOBJ_ADD)
243  kobj->state_add_uevent_sent = 1;
244  else if (action == KOBJ_REMOVE)
245  kobj->state_remove_uevent_sent = 1;
246 
247  mutex_lock(&uevent_sock_mutex);
248  /* we will send an event, so request a new sequence number */
249  retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
250  if (retval) {
251  mutex_unlock(&uevent_sock_mutex);
252  goto exit;
253  }
254 
255 #if defined(CONFIG_NET)
256  /* send netlink message */
257  list_for_each_entry(ue_sk, &uevent_sock_list, list) {
258  struct sock *uevent_sock = ue_sk->sk;
259  struct sk_buff *skb;
260  size_t len;
261 
262  if (!netlink_has_listeners(uevent_sock, 1))
263  continue;
264 
265  /* allocate message with the maximum possible size */
266  len = strlen(action_string) + strlen(devpath) + 2;
267  skb = alloc_skb(len + env->buflen, GFP_KERNEL);
268  if (skb) {
269  char *scratch;
270 
271  /* add header */
272  scratch = skb_put(skb, len);
273  sprintf(scratch, "%s@%s", action_string, devpath);
274 
275  /* copy keys to our continuous event payload buffer */
276  for (i = 0; i < env->envp_idx; i++) {
277  len = strlen(env->envp[i]) + 1;
278  scratch = skb_put(skb, len);
279  strcpy(scratch, env->envp[i]);
280  }
281 
282  NETLINK_CB(skb).dst_group = 1;
283  retval = netlink_broadcast_filtered(uevent_sock, skb,
284  0, 1, GFP_KERNEL,
285  kobj_bcast_filter,
286  kobj);
287  /* ENOBUFS should be handled in userspace */
288  if (retval == -ENOBUFS || retval == -ESRCH)
289  retval = 0;
290  } else
291  retval = -ENOMEM;
292  }
293 #endif
294  mutex_unlock(&uevent_sock_mutex);
295 
296  /* call uevent_helper, usually only enabled during early boot */
297  if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
298  char *argv [3];
299 
300  argv [0] = uevent_helper;
301  argv [1] = (char *)subsystem;
302  argv [2] = NULL;
303  retval = add_uevent_var(env, "HOME=/");
304  if (retval)
305  goto exit;
306  retval = add_uevent_var(env,
307  "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
308  if (retval)
309  goto exit;
310 
311  retval = call_usermodehelper(argv[0], argv,
312  env->envp, UMH_WAIT_EXEC);
313  }
314 
315 exit:
316  kfree(devpath);
317  kfree(env);
318  return retval;
319 }
321 
332 {
333  return kobject_uevent_env(kobj, action, NULL);
334 }
336 
345 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
346 {
347  va_list args;
348  int len;
349 
350  if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
351  WARN(1, KERN_ERR "add_uevent_var: too many keys\n");
352  return -ENOMEM;
353  }
354 
355  va_start(args, format);
356  len = vsnprintf(&env->buf[env->buflen],
357  sizeof(env->buf) - env->buflen,
358  format, args);
359  va_end(args);
360 
361  if (len >= (sizeof(env->buf) - env->buflen)) {
362  WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n");
363  return -ENOMEM;
364  }
365 
366  env->envp[env->envp_idx++] = &env->buf[env->buflen];
367  env->buflen += len + 1;
368  return 0;
369 }
371 
372 #if defined(CONFIG_NET)
373 static int uevent_net_init(struct net *net)
374 {
375  struct uevent_sock *ue_sk;
376  struct netlink_kernel_cfg cfg = {
377  .groups = 1,
378  .flags = NL_CFG_F_NONROOT_RECV,
379  };
380 
381  ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
382  if (!ue_sk)
383  return -ENOMEM;
384 
385  ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
386  if (!ue_sk->sk) {
388  "kobject_uevent: unable to create netlink socket!\n");
389  kfree(ue_sk);
390  return -ENODEV;
391  }
392  mutex_lock(&uevent_sock_mutex);
393  list_add_tail(&ue_sk->list, &uevent_sock_list);
394  mutex_unlock(&uevent_sock_mutex);
395  return 0;
396 }
397 
398 static void uevent_net_exit(struct net *net)
399 {
400  struct uevent_sock *ue_sk;
401 
402  mutex_lock(&uevent_sock_mutex);
403  list_for_each_entry(ue_sk, &uevent_sock_list, list) {
404  if (sock_net(ue_sk->sk) == net)
405  goto found;
406  }
407  mutex_unlock(&uevent_sock_mutex);
408  return;
409 
410 found:
411  list_del(&ue_sk->list);
412  mutex_unlock(&uevent_sock_mutex);
413 
414  netlink_kernel_release(ue_sk->sk);
415  kfree(ue_sk);
416 }
417 
418 static struct pernet_operations uevent_net_ops = {
419  .init = uevent_net_init,
420  .exit = uevent_net_exit,
421 };
422 
423 static int __init kobject_uevent_init(void)
424 {
425  return register_pernet_subsys(&uevent_net_ops);
426 }
427 
428 
429 postcore_initcall(kobject_uevent_init);
430 #endif