Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/lib/kobject_uevent.c

  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             <rml@novell.com>
 12  *      Kay Sievers             <kay.sievers@vrfy.org>
 13  *      Arjan van de Ven        <arjanv@redhat.com>
 14  *      Greg Kroah-Hartman      <greg@kroah.com>
 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/socket.h>
 24 #include <linux/skbuff.h>
 25 #include <linux/netlink.h>
 26 #include <net/sock.h>
 27 #include <net/net_namespace.h>
 28 
 29 
 30 u64 uevent_seqnum;
 31 #ifdef CONFIG_UEVENT_HELPER
 32 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
 33 #endif
 34 #ifdef CONFIG_NET
 35 struct uevent_sock {
 36         struct list_head list;
 37         struct sock *sk;
 38 };
 39 static LIST_HEAD(uevent_sock_list);
 40 #endif
 41 
 42 /* This lock protects uevent_seqnum and uevent_sock_list */
 43 static DEFINE_MUTEX(uevent_sock_mutex);
 44 
 45 /* the strings here must match the enum in include/linux/kobject.h */
 46 static const char *kobject_actions[] = {
 47         [KOBJ_ADD] =            "add",
 48         [KOBJ_REMOVE] =         "remove",
 49         [KOBJ_CHANGE] =         "change",
 50         [KOBJ_MOVE] =           "move",
 51         [KOBJ_ONLINE] =         "online",
 52         [KOBJ_OFFLINE] =        "offline",
 53 };
 54 
 55 /**
 56  * kobject_action_type - translate action string to numeric type
 57  *
 58  * @buf: buffer containing the action string, newline is ignored
 59  * @count: length of buffer
 60  * @type: pointer to the location to store the action type
 61  *
 62  * Returns 0 if the action string was recognized.
 63  */
 64 int kobject_action_type(const char *buf, size_t count,
 65                         enum kobject_action *type)
 66 {
 67         enum kobject_action action;
 68         int ret = -EINVAL;
 69 
 70         if (count && (buf[count-1] == '\n' || buf[count-1] == '\0'))
 71                 count--;
 72 
 73         if (!count)
 74                 goto out;
 75 
 76         for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
 77                 if (strncmp(kobject_actions[action], buf, count) != 0)
 78                         continue;
 79                 if (kobject_actions[action][count] != '\0')
 80                         continue;
 81                 *type = action;
 82                 ret = 0;
 83                 break;
 84         }
 85 out:
 86         return ret;
 87 }
 88 
 89 #ifdef CONFIG_NET
 90 static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
 91 {
 92         struct kobject *kobj = data, *ksobj;
 93         const struct kobj_ns_type_operations *ops;
 94 
 95         ops = kobj_ns_ops(kobj);
 96         if (!ops && kobj->kset) {
 97                 ksobj = &kobj->kset->kobj;
 98                 if (ksobj->parent != NULL)
 99                         ops = kobj_ns_ops(ksobj->parent);
100         }
101 
102         if (ops && ops->netlink_ns && kobj->ktype->namespace) {
103                 const void *sock_ns, *ns;
104                 ns = kobj->ktype->namespace(kobj);
105                 sock_ns = ops->netlink_ns(dsk);
106                 return sock_ns != ns;
107         }
108 
109         return 0;
110 }
111 #endif
112 
113 #ifdef CONFIG_UEVENT_HELPER
114 static int kobj_usermode_filter(struct kobject *kobj)
115 {
116         const struct kobj_ns_type_operations *ops;
117 
118         ops = kobj_ns_ops(kobj);
119         if (ops) {
120                 const void *init_ns, *ns;
121                 ns = kobj->ktype->namespace(kobj);
122                 init_ns = ops->initial_ns();
123                 return ns != init_ns;
124         }
125 
126         return 0;
127 }
128 
129 static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
130 {
131         int len;
132 
133         len = strlcpy(&env->buf[env->buflen], subsystem,
134                       sizeof(env->buf) - env->buflen);
135         if (len >= (sizeof(env->buf) - env->buflen)) {
136                 WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
137                 return -ENOMEM;
138         }
139 
140         env->argv[0] = uevent_helper;
141         env->argv[1] = &env->buf[env->buflen];
142         env->argv[2] = NULL;
143 
144         env->buflen += len + 1;
145         return 0;
146 }
147 
148 static void cleanup_uevent_env(struct subprocess_info *info)
149 {
150         kfree(info->data);
151 }
152 #endif
153 
154 /**
155  * kobject_uevent_env - send an uevent with environmental data
156  *
157  * @kobj: struct kobject that the action is happening to
158  * @action: action that is happening
159  * @envp_ext: pointer to environmental data
160  *
161  * Returns 0 if kobject_uevent_env() is completed with success or the
162  * corresponding error when it fails.
163  */
164 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
165                        char *envp_ext[])
166 {
167         struct kobj_uevent_env *env;
168         const char *action_string = kobject_actions[action];
169         const char *devpath = NULL;
170         const char *subsystem;
171         struct kobject *top_kobj;
172         struct kset *kset;
173         const struct kset_uevent_ops *uevent_ops;
174         int i = 0;
175         int retval = 0;
176 #ifdef CONFIG_NET
177         struct uevent_sock *ue_sk;
178 #endif
179 
180         pr_debug("kobject: '%s' (%p): %s\n",
181                  kobject_name(kobj), kobj, __func__);
182 
183         /* search the kset we belong to */
184         top_kobj = kobj;
185         while (!top_kobj->kset && top_kobj->parent)
186                 top_kobj = top_kobj->parent;
187 
188         if (!top_kobj->kset) {
189                 pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
190                          "without kset!\n", kobject_name(kobj), kobj,
191                          __func__);
192                 return -EINVAL;
193         }
194 
195         kset = top_kobj->kset;
196         uevent_ops = kset->uevent_ops;
197 
198         /* skip the event, if uevent_suppress is set*/
199         if (kobj->uevent_suppress) {
200                 pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
201                                  "caused the event to drop!\n",
202                                  kobject_name(kobj), kobj, __func__);
203                 return 0;
204         }
205         /* skip the event, if the filter returns zero. */
206         if (uevent_ops && uevent_ops->filter)
207                 if (!uevent_ops->filter(kset, kobj)) {
208                         pr_debug("kobject: '%s' (%p): %s: filter function "
209                                  "caused the event to drop!\n",
210                                  kobject_name(kobj), kobj, __func__);
211                         return 0;
212                 }
213 
214         /* originating subsystem */
215         if (uevent_ops && uevent_ops->name)
216                 subsystem = uevent_ops->name(kset, kobj);
217         else
218                 subsystem = kobject_name(&kset->kobj);
219         if (!subsystem) {
220                 pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
221                          "event to drop!\n", kobject_name(kobj), kobj,
222                          __func__);
223                 return 0;
224         }
225 
226         /* environment buffer */
227         env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
228         if (!env)
229                 return -ENOMEM;
230 
231         /* complete object path */
232         devpath = kobject_get_path(kobj, GFP_KERNEL);
233         if (!devpath) {
234                 retval = -ENOENT;
235                 goto exit;
236         }
237 
238         /* default keys */
239         retval = add_uevent_var(env, "ACTION=%s", action_string);
240         if (retval)
241                 goto exit;
242         retval = add_uevent_var(env, "DEVPATH=%s", devpath);
243         if (retval)
244                 goto exit;
245         retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
246         if (retval)
247                 goto exit;
248 
249         /* keys passed in from the caller */
250         if (envp_ext) {
251                 for (i = 0; envp_ext[i]; i++) {
252                         retval = add_uevent_var(env, "%s", envp_ext[i]);
253                         if (retval)
254                                 goto exit;
255                 }
256         }
257 
258         /* let the kset specific function add its stuff */
259         if (uevent_ops && uevent_ops->uevent) {
260                 retval = uevent_ops->uevent(kset, kobj, env);
261                 if (retval) {
262                         pr_debug("kobject: '%s' (%p): %s: uevent() returned "
263                                  "%d\n", kobject_name(kobj), kobj,
264                                  __func__, retval);
265                         goto exit;
266                 }
267         }
268 
269         /*
270          * Mark "add" and "remove" events in the object to ensure proper
271          * events to userspace during automatic cleanup. If the object did
272          * send an "add" event, "remove" will automatically generated by
273          * the core, if not already done by the caller.
274          */
275         if (action == KOBJ_ADD)
276                 kobj->state_add_uevent_sent = 1;
277         else if (action == KOBJ_REMOVE)
278                 kobj->state_remove_uevent_sent = 1;
279 
280         mutex_lock(&uevent_sock_mutex);
281         /* we will send an event, so request a new sequence number */
282         retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
283         if (retval) {
284                 mutex_unlock(&uevent_sock_mutex);
285                 goto exit;
286         }
287 
288 #if defined(CONFIG_NET)
289         /* send netlink message */
290         list_for_each_entry(ue_sk, &uevent_sock_list, list) {
291                 struct sock *uevent_sock = ue_sk->sk;
292                 struct sk_buff *skb;
293                 size_t len;
294 
295                 if (!netlink_has_listeners(uevent_sock, 1))
296                         continue;
297 
298                 /* allocate message with the maximum possible size */
299                 len = strlen(action_string) + strlen(devpath) + 2;
300                 skb = alloc_skb(len + env->buflen, GFP_KERNEL);
301                 if (skb) {
302                         char *scratch;
303 
304                         /* add header */
305                         scratch = skb_put(skb, len);
306                         sprintf(scratch, "%s@%s", action_string, devpath);
307 
308                         /* copy keys to our continuous event payload buffer */
309                         for (i = 0; i < env->envp_idx; i++) {
310                                 len = strlen(env->envp[i]) + 1;
311                                 scratch = skb_put(skb, len);
312                                 strcpy(scratch, env->envp[i]);
313                         }
314 
315                         NETLINK_CB(skb).dst_group = 1;
316                         retval = netlink_broadcast_filtered(uevent_sock, skb,
317                                                             0, 1, GFP_KERNEL,
318                                                             kobj_bcast_filter,
319                                                             kobj);
320                         /* ENOBUFS should be handled in userspace */
321                         if (retval == -ENOBUFS || retval == -ESRCH)
322                                 retval = 0;
323                 } else
324                         retval = -ENOMEM;
325         }
326 #endif
327         mutex_unlock(&uevent_sock_mutex);
328 
329 #ifdef CONFIG_UEVENT_HELPER
330         /* call uevent_helper, usually only enabled during early boot */
331         if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
332                 struct subprocess_info *info;
333 
334                 retval = add_uevent_var(env, "HOME=/");
335                 if (retval)
336                         goto exit;
337                 retval = add_uevent_var(env,
338                                         "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
339                 if (retval)
340                         goto exit;
341                 retval = init_uevent_argv(env, subsystem);
342                 if (retval)
343                         goto exit;
344 
345                 retval = -ENOMEM;
346                 info = call_usermodehelper_setup(env->argv[0], env->argv,
347                                                  env->envp, GFP_KERNEL,
348                                                  NULL, cleanup_uevent_env, env);
349                 if (info) {
350                         retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
351                         env = NULL;     /* freed by cleanup_uevent_env */
352                 }
353         }
354 #endif
355 
356 exit:
357         kfree(devpath);
358         kfree(env);
359         return retval;
360 }
361 EXPORT_SYMBOL_GPL(kobject_uevent_env);
362 
363 /**
364  * kobject_uevent - notify userspace by sending an uevent
365  *
366  * @kobj: struct kobject that the action is happening to
367  * @action: action that is happening
368  *
369  * Returns 0 if kobject_uevent() is completed with success or the
370  * corresponding error when it fails.
371  */
372 int kobject_uevent(struct kobject *kobj, enum kobject_action action)
373 {
374         return kobject_uevent_env(kobj, action, NULL);
375 }
376 EXPORT_SYMBOL_GPL(kobject_uevent);
377 
378 /**
379  * add_uevent_var - add key value string to the environment buffer
380  * @env: environment buffer structure
381  * @format: printf format for the key=value pair
382  *
383  * Returns 0 if environment variable was added successfully or -ENOMEM
384  * if no space was available.
385  */
386 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
387 {
388         va_list args;
389         int len;
390 
391         if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
392                 WARN(1, KERN_ERR "add_uevent_var: too many keys\n");
393                 return -ENOMEM;
394         }
395 
396         va_start(args, format);
397         len = vsnprintf(&env->buf[env->buflen],
398                         sizeof(env->buf) - env->buflen,
399                         format, args);
400         va_end(args);
401 
402         if (len >= (sizeof(env->buf) - env->buflen)) {
403                 WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n");
404                 return -ENOMEM;
405         }
406 
407         env->envp[env->envp_idx++] = &env->buf[env->buflen];
408         env->buflen += len + 1;
409         return 0;
410 }
411 EXPORT_SYMBOL_GPL(add_uevent_var);
412 
413 #if defined(CONFIG_NET)
414 static int uevent_net_init(struct net *net)
415 {
416         struct uevent_sock *ue_sk;
417         struct netlink_kernel_cfg cfg = {
418                 .groups = 1,
419                 .flags  = NL_CFG_F_NONROOT_RECV,
420         };
421 
422         ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
423         if (!ue_sk)
424                 return -ENOMEM;
425 
426         ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
427         if (!ue_sk->sk) {
428                 printk(KERN_ERR
429                        "kobject_uevent: unable to create netlink socket!\n");
430                 kfree(ue_sk);
431                 return -ENODEV;
432         }
433         mutex_lock(&uevent_sock_mutex);
434         list_add_tail(&ue_sk->list, &uevent_sock_list);
435         mutex_unlock(&uevent_sock_mutex);
436         return 0;
437 }
438 
439 static void uevent_net_exit(struct net *net)
440 {
441         struct uevent_sock *ue_sk;
442 
443         mutex_lock(&uevent_sock_mutex);
444         list_for_each_entry(ue_sk, &uevent_sock_list, list) {
445                 if (sock_net(ue_sk->sk) == net)
446                         goto found;
447         }
448         mutex_unlock(&uevent_sock_mutex);
449         return;
450 
451 found:
452         list_del(&ue_sk->list);
453         mutex_unlock(&uevent_sock_mutex);
454 
455         netlink_kernel_release(ue_sk->sk);
456         kfree(ue_sk);
457 }
458 
459 static struct pernet_operations uevent_net_ops = {
460         .init   = uevent_net_init,
461         .exit   = uevent_net_exit,
462 };
463 
464 static int __init kobject_uevent_init(void)
465 {
466         return register_pernet_subsys(&uevent_net_ops);
467 }
468 
469 
470 postcore_initcall(kobject_uevent_init);
471 #endif
472 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us