Back to home page

LXR

 
 

    


0001 /*
0002  * kernel userspace event delivery
0003  *
0004  * Copyright (C) 2004 Red Hat, Inc.  All rights reserved.
0005  * Copyright (C) 2004 Novell, Inc.  All rights reserved.
0006  * Copyright (C) 2004 IBM, Inc. All rights reserved.
0007  *
0008  * Licensed under the GNU GPL v2.
0009  *
0010  * Authors:
0011  *  Robert Love     <rml@novell.com>
0012  *  Kay Sievers     <kay.sievers@vrfy.org>
0013  *  Arjan van de Ven    <arjanv@redhat.com>
0014  *  Greg Kroah-Hartman  <greg@kroah.com>
0015  */
0016 
0017 #include <linux/spinlock.h>
0018 #include <linux/string.h>
0019 #include <linux/kobject.h>
0020 #include <linux/export.h>
0021 #include <linux/kmod.h>
0022 #include <linux/slab.h>
0023 #include <linux/socket.h>
0024 #include <linux/skbuff.h>
0025 #include <linux/netlink.h>
0026 #include <net/sock.h>
0027 #include <net/net_namespace.h>
0028 
0029 
0030 u64 uevent_seqnum;
0031 #ifdef CONFIG_UEVENT_HELPER
0032 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
0033 #endif
0034 #ifdef CONFIG_NET
0035 struct uevent_sock {
0036     struct list_head list;
0037     struct sock *sk;
0038 };
0039 static LIST_HEAD(uevent_sock_list);
0040 #endif
0041 
0042 /* This lock protects uevent_seqnum and uevent_sock_list */
0043 static DEFINE_MUTEX(uevent_sock_mutex);
0044 
0045 /* the strings here must match the enum in include/linux/kobject.h */
0046 static const char *kobject_actions[] = {
0047     [KOBJ_ADD] =        "add",
0048     [KOBJ_REMOVE] =     "remove",
0049     [KOBJ_CHANGE] =     "change",
0050     [KOBJ_MOVE] =       "move",
0051     [KOBJ_ONLINE] =     "online",
0052     [KOBJ_OFFLINE] =    "offline",
0053 };
0054 
0055 /**
0056  * kobject_action_type - translate action string to numeric type
0057  *
0058  * @buf: buffer containing the action string, newline is ignored
0059  * @count: length of buffer
0060  * @type: pointer to the location to store the action type
0061  *
0062  * Returns 0 if the action string was recognized.
0063  */
0064 int kobject_action_type(const char *buf, size_t count,
0065             enum kobject_action *type)
0066 {
0067     enum kobject_action action;
0068     int ret = -EINVAL;
0069 
0070     if (count && (buf[count-1] == '\n' || buf[count-1] == '\0'))
0071         count--;
0072 
0073     if (!count)
0074         goto out;
0075 
0076     for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) {
0077         if (strncmp(kobject_actions[action], buf, count) != 0)
0078             continue;
0079         if (kobject_actions[action][count] != '\0')
0080             continue;
0081         *type = action;
0082         ret = 0;
0083         break;
0084     }
0085 out:
0086     return ret;
0087 }
0088 
0089 #ifdef CONFIG_NET
0090 static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
0091 {
0092     struct kobject *kobj = data, *ksobj;
0093     const struct kobj_ns_type_operations *ops;
0094 
0095     ops = kobj_ns_ops(kobj);
0096     if (!ops && kobj->kset) {
0097         ksobj = &kobj->kset->kobj;
0098         if (ksobj->parent != NULL)
0099             ops = kobj_ns_ops(ksobj->parent);
0100     }
0101 
0102     if (ops && ops->netlink_ns && kobj->ktype->namespace) {
0103         const void *sock_ns, *ns;
0104         ns = kobj->ktype->namespace(kobj);
0105         sock_ns = ops->netlink_ns(dsk);
0106         return sock_ns != ns;
0107     }
0108 
0109     return 0;
0110 }
0111 #endif
0112 
0113 #ifdef CONFIG_UEVENT_HELPER
0114 static int kobj_usermode_filter(struct kobject *kobj)
0115 {
0116     const struct kobj_ns_type_operations *ops;
0117 
0118     ops = kobj_ns_ops(kobj);
0119     if (ops) {
0120         const void *init_ns, *ns;
0121         ns = kobj->ktype->namespace(kobj);
0122         init_ns = ops->initial_ns();
0123         return ns != init_ns;
0124     }
0125 
0126     return 0;
0127 }
0128 
0129 static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
0130 {
0131     int len;
0132 
0133     len = strlcpy(&env->buf[env->buflen], subsystem,
0134               sizeof(env->buf) - env->buflen);
0135     if (len >= (sizeof(env->buf) - env->buflen)) {
0136         WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
0137         return -ENOMEM;
0138     }
0139 
0140     env->argv[0] = uevent_helper;
0141     env->argv[1] = &env->buf[env->buflen];
0142     env->argv[2] = NULL;
0143 
0144     env->buflen += len + 1;
0145     return 0;
0146 }
0147 
0148 static void cleanup_uevent_env(struct subprocess_info *info)
0149 {
0150     kfree(info->data);
0151 }
0152 #endif
0153 
0154 /**
0155  * kobject_uevent_env - send an uevent with environmental data
0156  *
0157  * @kobj: struct kobject that the action is happening to
0158  * @action: action that is happening
0159  * @envp_ext: pointer to environmental data
0160  *
0161  * Returns 0 if kobject_uevent_env() is completed with success or the
0162  * corresponding error when it fails.
0163  */
0164 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
0165                char *envp_ext[])
0166 {
0167     struct kobj_uevent_env *env;
0168     const char *action_string = kobject_actions[action];
0169     const char *devpath = NULL;
0170     const char *subsystem;
0171     struct kobject *top_kobj;
0172     struct kset *kset;
0173     const struct kset_uevent_ops *uevent_ops;
0174     int i = 0;
0175     int retval = 0;
0176 #ifdef CONFIG_NET
0177     struct uevent_sock *ue_sk;
0178 #endif
0179 
0180     pr_debug("kobject: '%s' (%p): %s\n",
0181          kobject_name(kobj), kobj, __func__);
0182 
0183     /* search the kset we belong to */
0184     top_kobj = kobj;
0185     while (!top_kobj->kset && top_kobj->parent)
0186         top_kobj = top_kobj->parent;
0187 
0188     if (!top_kobj->kset) {
0189         pr_debug("kobject: '%s' (%p): %s: attempted to send uevent "
0190              "without kset!\n", kobject_name(kobj), kobj,
0191              __func__);
0192         return -EINVAL;
0193     }
0194 
0195     kset = top_kobj->kset;
0196     uevent_ops = kset->uevent_ops;
0197 
0198     /* skip the event, if uevent_suppress is set*/
0199     if (kobj->uevent_suppress) {
0200         pr_debug("kobject: '%s' (%p): %s: uevent_suppress "
0201                  "caused the event to drop!\n",
0202                  kobject_name(kobj), kobj, __func__);
0203         return 0;
0204     }
0205     /* skip the event, if the filter returns zero. */
0206     if (uevent_ops && uevent_ops->filter)
0207         if (!uevent_ops->filter(kset, kobj)) {
0208             pr_debug("kobject: '%s' (%p): %s: filter function "
0209                  "caused the event to drop!\n",
0210                  kobject_name(kobj), kobj, __func__);
0211             return 0;
0212         }
0213 
0214     /* originating subsystem */
0215     if (uevent_ops && uevent_ops->name)
0216         subsystem = uevent_ops->name(kset, kobj);
0217     else
0218         subsystem = kobject_name(&kset->kobj);
0219     if (!subsystem) {
0220         pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the "
0221              "event to drop!\n", kobject_name(kobj), kobj,
0222              __func__);
0223         return 0;
0224     }
0225 
0226     /* environment buffer */
0227     env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
0228     if (!env)
0229         return -ENOMEM;
0230 
0231     /* complete object path */
0232     devpath = kobject_get_path(kobj, GFP_KERNEL);
0233     if (!devpath) {
0234         retval = -ENOENT;
0235         goto exit;
0236     }
0237 
0238     /* default keys */
0239     retval = add_uevent_var(env, "ACTION=%s", action_string);
0240     if (retval)
0241         goto exit;
0242     retval = add_uevent_var(env, "DEVPATH=%s", devpath);
0243     if (retval)
0244         goto exit;
0245     retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
0246     if (retval)
0247         goto exit;
0248 
0249     /* keys passed in from the caller */
0250     if (envp_ext) {
0251         for (i = 0; envp_ext[i]; i++) {
0252             retval = add_uevent_var(env, "%s", envp_ext[i]);
0253             if (retval)
0254                 goto exit;
0255         }
0256     }
0257 
0258     /* let the kset specific function add its stuff */
0259     if (uevent_ops && uevent_ops->uevent) {
0260         retval = uevent_ops->uevent(kset, kobj, env);
0261         if (retval) {
0262             pr_debug("kobject: '%s' (%p): %s: uevent() returned "
0263                  "%d\n", kobject_name(kobj), kobj,
0264                  __func__, retval);
0265             goto exit;
0266         }
0267     }
0268 
0269     /*
0270      * Mark "add" and "remove" events in the object to ensure proper
0271      * events to userspace during automatic cleanup. If the object did
0272      * send an "add" event, "remove" will automatically generated by
0273      * the core, if not already done by the caller.
0274      */
0275     if (action == KOBJ_ADD)
0276         kobj->state_add_uevent_sent = 1;
0277     else if (action == KOBJ_REMOVE)
0278         kobj->state_remove_uevent_sent = 1;
0279 
0280     mutex_lock(&uevent_sock_mutex);
0281     /* we will send an event, so request a new sequence number */
0282     retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
0283     if (retval) {
0284         mutex_unlock(&uevent_sock_mutex);
0285         goto exit;
0286     }
0287 
0288 #if defined(CONFIG_NET)
0289     /* send netlink message */
0290     list_for_each_entry(ue_sk, &uevent_sock_list, list) {
0291         struct sock *uevent_sock = ue_sk->sk;
0292         struct sk_buff *skb;
0293         size_t len;
0294 
0295         if (!netlink_has_listeners(uevent_sock, 1))
0296             continue;
0297 
0298         /* allocate message with the maximum possible size */
0299         len = strlen(action_string) + strlen(devpath) + 2;
0300         skb = alloc_skb(len + env->buflen, GFP_KERNEL);
0301         if (skb) {
0302             char *scratch;
0303 
0304             /* add header */
0305             scratch = skb_put(skb, len);
0306             sprintf(scratch, "%s@%s", action_string, devpath);
0307 
0308             /* copy keys to our continuous event payload buffer */
0309             for (i = 0; i < env->envp_idx; i++) {
0310                 len = strlen(env->envp[i]) + 1;
0311                 scratch = skb_put(skb, len);
0312                 strcpy(scratch, env->envp[i]);
0313             }
0314 
0315             NETLINK_CB(skb).dst_group = 1;
0316             retval = netlink_broadcast_filtered(uevent_sock, skb,
0317                                 0, 1, GFP_KERNEL,
0318                                 kobj_bcast_filter,
0319                                 kobj);
0320             /* ENOBUFS should be handled in userspace */
0321             if (retval == -ENOBUFS || retval == -ESRCH)
0322                 retval = 0;
0323         } else
0324             retval = -ENOMEM;
0325     }
0326 #endif
0327     mutex_unlock(&uevent_sock_mutex);
0328 
0329 #ifdef CONFIG_UEVENT_HELPER
0330     /* call uevent_helper, usually only enabled during early boot */
0331     if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
0332         struct subprocess_info *info;
0333 
0334         retval = add_uevent_var(env, "HOME=/");
0335         if (retval)
0336             goto exit;
0337         retval = add_uevent_var(env,
0338                     "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
0339         if (retval)
0340             goto exit;
0341         retval = init_uevent_argv(env, subsystem);
0342         if (retval)
0343             goto exit;
0344 
0345         retval = -ENOMEM;
0346         info = call_usermodehelper_setup(env->argv[0], env->argv,
0347                          env->envp, GFP_KERNEL,
0348                          NULL, cleanup_uevent_env, env);
0349         if (info) {
0350             retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
0351             env = NULL; /* freed by cleanup_uevent_env */
0352         }
0353     }
0354 #endif
0355 
0356 exit:
0357     kfree(devpath);
0358     kfree(env);
0359     return retval;
0360 }
0361 EXPORT_SYMBOL_GPL(kobject_uevent_env);
0362 
0363 /**
0364  * kobject_uevent - notify userspace by sending an uevent
0365  *
0366  * @kobj: struct kobject that the action is happening to
0367  * @action: action that is happening
0368  *
0369  * Returns 0 if kobject_uevent() is completed with success or the
0370  * corresponding error when it fails.
0371  */
0372 int kobject_uevent(struct kobject *kobj, enum kobject_action action)
0373 {
0374     return kobject_uevent_env(kobj, action, NULL);
0375 }
0376 EXPORT_SYMBOL_GPL(kobject_uevent);
0377 
0378 /**
0379  * add_uevent_var - add key value string to the environment buffer
0380  * @env: environment buffer structure
0381  * @format: printf format for the key=value pair
0382  *
0383  * Returns 0 if environment variable was added successfully or -ENOMEM
0384  * if no space was available.
0385  */
0386 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
0387 {
0388     va_list args;
0389     int len;
0390 
0391     if (env->envp_idx >= ARRAY_SIZE(env->envp)) {
0392         WARN(1, KERN_ERR "add_uevent_var: too many keys\n");
0393         return -ENOMEM;
0394     }
0395 
0396     va_start(args, format);
0397     len = vsnprintf(&env->buf[env->buflen],
0398             sizeof(env->buf) - env->buflen,
0399             format, args);
0400     va_end(args);
0401 
0402     if (len >= (sizeof(env->buf) - env->buflen)) {
0403         WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n");
0404         return -ENOMEM;
0405     }
0406 
0407     env->envp[env->envp_idx++] = &env->buf[env->buflen];
0408     env->buflen += len + 1;
0409     return 0;
0410 }
0411 EXPORT_SYMBOL_GPL(add_uevent_var);
0412 
0413 #if defined(CONFIG_NET)
0414 static int uevent_net_init(struct net *net)
0415 {
0416     struct uevent_sock *ue_sk;
0417     struct netlink_kernel_cfg cfg = {
0418         .groups = 1,
0419         .flags  = NL_CFG_F_NONROOT_RECV,
0420     };
0421 
0422     ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
0423     if (!ue_sk)
0424         return -ENOMEM;
0425 
0426     ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT, &cfg);
0427     if (!ue_sk->sk) {
0428         printk(KERN_ERR
0429                "kobject_uevent: unable to create netlink socket!\n");
0430         kfree(ue_sk);
0431         return -ENODEV;
0432     }
0433     mutex_lock(&uevent_sock_mutex);
0434     list_add_tail(&ue_sk->list, &uevent_sock_list);
0435     mutex_unlock(&uevent_sock_mutex);
0436     return 0;
0437 }
0438 
0439 static void uevent_net_exit(struct net *net)
0440 {
0441     struct uevent_sock *ue_sk;
0442 
0443     mutex_lock(&uevent_sock_mutex);
0444     list_for_each_entry(ue_sk, &uevent_sock_list, list) {
0445         if (sock_net(ue_sk->sk) == net)
0446             goto found;
0447     }
0448     mutex_unlock(&uevent_sock_mutex);
0449     return;
0450 
0451 found:
0452     list_del(&ue_sk->list);
0453     mutex_unlock(&uevent_sock_mutex);
0454 
0455     netlink_kernel_release(ue_sk->sk);
0456     kfree(ue_sk);
0457 }
0458 
0459 static struct pernet_operations uevent_net_ops = {
0460     .init   = uevent_net_init,
0461     .exit   = uevent_net_exit,
0462 };
0463 
0464 static int __init kobject_uevent_init(void)
0465 {
0466     return register_pernet_subsys(&uevent_net_ops);
0467 }
0468 
0469 
0470 postcore_initcall(kobject_uevent_init);
0471 #endif