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/module.h> 21 22 #include <linux/socket.h> 23 #include <linux/skbuff.h> 24 #include <linux/netlink.h> 25 #include <net/sock.h> 26 27 28 u64 uevent_seqnum; 29 char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; 30 static DEFINE_SPINLOCK(sequence_lock); 31 #if defined(CONFIG_NET) 32 static struct sock *uevent_sock; 33 #endif 34 35 /* the strings here must match the enum in include/linux/kobject.h */ 36 static const char *kobject_actions[] = { 37 [KOBJ_ADD] = "add", 38 [KOBJ_REMOVE] = "remove", 39 [KOBJ_CHANGE] = "change", 40 [KOBJ_MOVE] = "move", 41 [KOBJ_ONLINE] = "online", 42 [KOBJ_OFFLINE] = "offline", 43 }; 44 45 /** 46 * kobject_action_type - translate action string to numeric type 47 * 48 * @buf: buffer containing the action string, newline is ignored 49 * @len: length of buffer 50 * @type: pointer to the location to store the action type 51 * 52 * Returns 0 if the action string was recognized. 53 */ 54 int kobject_action_type(const char *buf, size_t count, 55 enum kobject_action *type) 56 { 57 enum kobject_action action; 58 int ret = -EINVAL; 59 60 if (count && (buf[count-1] == '\n' || buf[count-1] == '\0')) 61 count--; 62 63 if (!count) 64 goto out; 65 66 for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { 67 if (strncmp(kobject_actions[action], buf, count) != 0) 68 continue; 69 if (kobject_actions[action][count] != '\0') 70 continue; 71 *type = action; 72 ret = 0; 73 break; 74 } 75 out: 76 return ret; 77 } 78 79 /** 80 * kobject_uevent_env - send an uevent with environmental data 81 * 82 * @action: action that is happening 83 * @kobj: struct kobject that the action is happening to 84 * @envp_ext: pointer to environmental data 85 * 86 * Returns 0 if kobject_uevent() is completed with success or the 87 * corresponding error when it fails. 88 */ 89 int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, 90 char *envp_ext[]) 91 { 92 struct kobj_uevent_env *env; 93 const char *action_string = kobject_actions[action]; 94 const char *devpath = NULL; 95 const char *subsystem; 96 struct kobject *top_kobj; 97 struct kset *kset; 98 struct kset_uevent_ops *uevent_ops; 99 u64 seq; 100 int i = 0; 101 int retval = 0; 102 103 pr_debug("kobject: '%s' (%p): %s\n", 104 kobject_name(kobj), kobj, __func__); 105 106 /* search the kset we belong to */ 107 top_kobj = kobj; 108 while (!top_kobj->kset && top_kobj->parent) 109 top_kobj = top_kobj->parent; 110 111 if (!top_kobj->kset) { 112 pr_debug("kobject: '%s' (%p): %s: attempted to send uevent " 113 "without kset!\n", kobject_name(kobj), kobj, 114 __func__); 115 return -EINVAL; 116 } 117 118 kset = top_kobj->kset; 119 uevent_ops = kset->uevent_ops; 120 121 /* skip the event, if the filter returns zero. */ 122 if (uevent_ops && uevent_ops->filter) 123 if (!uevent_ops->filter(kset, kobj)) { 124 pr_debug("kobject: '%s' (%p): %s: filter function " 125 "caused the event to drop!\n", 126 kobject_name(kobj), kobj, __func__); 127 return 0; 128 } 129 130 /* originating subsystem */ 131 if (uevent_ops && uevent_ops->name) 132 subsystem = uevent_ops->name(kset, kobj); 133 else 134 subsystem = kobject_name(&kset->kobj); 135 if (!subsystem) { 136 pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the " 137 "event to drop!\n", kobject_name(kobj), kobj, 138 __func__); 139 return 0; 140 } 141 142 /* environment buffer */ 143 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); 144 if (!env) 145 return -ENOMEM; 146 147 /* complete object path */ 148 devpath = kobject_get_path(kobj, GFP_KERNEL); 149 if (!devpath) { 150 retval = -ENOENT; 151 goto exit; 152 } 153 154 /* default keys */ 155 retval = add_uevent_var(env, "ACTION=%s", action_string); 156 if (retval) 157 goto exit; 158 retval = add_uevent_var(env, "DEVPATH=%s", devpath); 159 if (retval) 160 goto exit; 161 retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); 162 if (retval) 163 goto exit; 164 165 /* keys passed in from the caller */ 166 if (envp_ext) { 167 for (i = 0; envp_ext[i]; i++) { 168 retval = add_uevent_var(env, envp_ext[i]); 169 if (retval) 170 goto exit; 171 } 172 } 173 174 /* let the kset specific function add its stuff */ 175 if (uevent_ops && uevent_ops->uevent) { 176 retval = uevent_ops->uevent(kset, kobj, env); 177 if (retval) { 178 pr_debug("kobject: '%s' (%p): %s: uevent() returned " 179 "%d\n", kobject_name(kobj), kobj, 180 __func__, retval); 181 goto exit; 182 } 183 } 184 185 /* 186 * Mark "add" and "remove" events in the object to ensure proper 187 * events to userspace during automatic cleanup. If the object did 188 * send an "add" event, "remove" will automatically generated by 189 * the core, if not already done by the caller. 190 */ 191 if (action == KOBJ_ADD) 192 kobj->state_add_uevent_sent = 1; 193 else if (action == KOBJ_REMOVE) 194 kobj->state_remove_uevent_sent = 1; 195 196 /* we will send an event, so request a new sequence number */ 197 spin_lock(&sequence_lock); 198 seq = ++uevent_seqnum; 199 spin_unlock(&sequence_lock); 200 retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); 201 if (retval) 202 goto exit; 203 204 #if defined(CONFIG_NET) 205 /* send netlink message */ 206 if (uevent_sock) { 207 struct sk_buff *skb; 208 size_t len; 209 210 /* allocate message with the maximum possible size */ 211 len = strlen(action_string) + strlen(devpath) + 2; 212 skb = alloc_skb(len + env->buflen, GFP_KERNEL); 213 if (skb) { 214 char *scratch; 215 216 /* add header */ 217 scratch = skb_put(skb, len); 218 sprintf(scratch, "%s@%s", action_string, devpath); 219 220 /* copy keys to our continuous event payload buffer */ 221 for (i = 0; i < env->envp_idx; i++) { 222 len = strlen(env->envp[i]) + 1; 223 scratch = skb_put(skb, len); 224 strcpy(scratch, env->envp[i]); 225 } 226 227 NETLINK_CB(skb).dst_group = 1; 228 netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); 229 } 230 } 231 #endif 232 233 /* call uevent_helper, usually only enabled during early boot */ 234 if (uevent_helper[0]) { 235 char *argv [3]; 236 237 argv [0] = uevent_helper; 238 argv [1] = (char *)subsystem; 239 argv [2] = NULL; 240 retval = add_uevent_var(env, "HOME=/"); 241 if (retval) 242 goto exit; 243 retval = add_uevent_var(env, 244 "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 245 if (retval) 246 goto exit; 247 248 retval = call_usermodehelper(argv[0], argv, 249 env->envp, UMH_WAIT_EXEC); 250 } 251 252 exit: 253 kfree(devpath); 254 kfree(env); 255 return retval; 256 } 257 EXPORT_SYMBOL_GPL(kobject_uevent_env); 258 259 /** 260 * kobject_uevent - notify userspace by ending an uevent 261 * 262 * @action: action that is happening 263 * @kobj: struct kobject that the action is happening to 264 * 265 * Returns 0 if kobject_uevent() is completed with success or the 266 * corresponding error when it fails. 267 */ 268 int kobject_uevent(struct kobject *kobj, enum kobject_action action) 269 { 270 return kobject_uevent_env(kobj, action, NULL); 271 } 272 EXPORT_SYMBOL_GPL(kobject_uevent); 273 274 /** 275 * add_uevent_var - add key value string to the environment buffer 276 * @env: environment buffer structure 277 * @format: printf format for the key=value pair 278 * 279 * Returns 0 if environment variable was added successfully or -ENOMEM 280 * if no space was available. 281 */ 282 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) 283 { 284 va_list args; 285 int len; 286 287 if (env->envp_idx >= ARRAY_SIZE(env->envp)) { 288 WARN(1, KERN_ERR "add_uevent_var: too many keys\n"); 289 return -ENOMEM; 290 } 291 292 va_start(args, format); 293 len = vsnprintf(&env->buf[env->buflen], 294 sizeof(env->buf) - env->buflen, 295 format, args); 296 va_end(args); 297 298 if (len >= (sizeof(env->buf) - env->buflen)) { 299 WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n"); 300 return -ENOMEM; 301 } 302 303 env->envp[env->envp_idx++] = &env->buf[env->buflen]; 304 env->buflen += len + 1; 305 return 0; 306 } 307 EXPORT_SYMBOL_GPL(add_uevent_var); 308 309 #if defined(CONFIG_NET) 310 static int __init kobject_uevent_init(void) 311 { 312 uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, 313 1, NULL, NULL, THIS_MODULE); 314 if (!uevent_sock) { 315 printk(KERN_ERR 316 "kobject_uevent: unable to create netlink socket!\n"); 317 return -ENODEV; 318 } 319 320 return 0; 321 } 322 323 postcore_initcall(kobject_uevent_init); 324 #endif 325