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 uevent_suppress is set*/ 122 if (kobj->uevent_suppress) { 123 pr_debug("kobject: '%s' (%p): %s: uevent_suppress " 124 "caused the event to drop!\n", 125 kobject_name(kobj), kobj, __func__); 126 return 0; 127 } 128 /* skip the event, if the filter returns zero. */ 129 if (uevent_ops && uevent_ops->filter) 130 if (!uevent_ops->filter(kset, kobj)) { 131 pr_debug("kobject: '%s' (%p): %s: filter function " 132 "caused the event to drop!\n", 133 kobject_name(kobj), kobj, __func__); 134 return 0; 135 } 136 137 /* originating subsystem */ 138 if (uevent_ops && uevent_ops->name) 139 subsystem = uevent_ops->name(kset, kobj); 140 else 141 subsystem = kobject_name(&kset->kobj); 142 if (!subsystem) { 143 pr_debug("kobject: '%s' (%p): %s: unset subsystem caused the " 144 "event to drop!\n", kobject_name(kobj), kobj, 145 __func__); 146 return 0; 147 } 148 149 /* environment buffer */ 150 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL); 151 if (!env) 152 return -ENOMEM; 153 154 /* complete object path */ 155 devpath = kobject_get_path(kobj, GFP_KERNEL); 156 if (!devpath) { 157 retval = -ENOENT; 158 goto exit; 159 } 160 161 /* default keys */ 162 retval = add_uevent_var(env, "ACTION=%s", action_string); 163 if (retval) 164 goto exit; 165 retval = add_uevent_var(env, "DEVPATH=%s", devpath); 166 if (retval) 167 goto exit; 168 retval = add_uevent_var(env, "SUBSYSTEM=%s", subsystem); 169 if (retval) 170 goto exit; 171 172 /* keys passed in from the caller */ 173 if (envp_ext) { 174 for (i = 0; envp_ext[i]; i++) { 175 retval = add_uevent_var(env, "%s", envp_ext[i]); 176 if (retval) 177 goto exit; 178 } 179 } 180 181 /* let the kset specific function add its stuff */ 182 if (uevent_ops && uevent_ops->uevent) { 183 retval = uevent_ops->uevent(kset, kobj, env); 184 if (retval) { 185 pr_debug("kobject: '%s' (%p): %s: uevent() returned " 186 "%d\n", kobject_name(kobj), kobj, 187 __func__, retval); 188 goto exit; 189 } 190 } 191 192 /* 193 * Mark "add" and "remove" events in the object to ensure proper 194 * events to userspace during automatic cleanup. If the object did 195 * send an "add" event, "remove" will automatically generated by 196 * the core, if not already done by the caller. 197 */ 198 if (action == KOBJ_ADD) 199 kobj->state_add_uevent_sent = 1; 200 else if (action == KOBJ_REMOVE) 201 kobj->state_remove_uevent_sent = 1; 202 203 /* we will send an event, so request a new sequence number */ 204 spin_lock(&sequence_lock); 205 seq = ++uevent_seqnum; 206 spin_unlock(&sequence_lock); 207 retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); 208 if (retval) 209 goto exit; 210 211 #if defined(CONFIG_NET) 212 /* send netlink message */ 213 if (uevent_sock) { 214 struct sk_buff *skb; 215 size_t len; 216 217 /* allocate message with the maximum possible size */ 218 len = strlen(action_string) + strlen(devpath) + 2; 219 skb = alloc_skb(len + env->buflen, GFP_KERNEL); 220 if (skb) { 221 char *scratch; 222 223 /* add header */ 224 scratch = skb_put(skb, len); 225 sprintf(scratch, "%s@%s", action_string, devpath); 226 227 /* copy keys to our continuous event payload buffer */ 228 for (i = 0; i < env->envp_idx; i++) { 229 len = strlen(env->envp[i]) + 1; 230 scratch = skb_put(skb, len); 231 strcpy(scratch, env->envp[i]); 232 } 233 234 NETLINK_CB(skb).dst_group = 1; 235 retval = netlink_broadcast(uevent_sock, skb, 0, 1, 236 GFP_KERNEL); 237 /* ENOBUFS should be handled in userspace */ 238 if (retval == -ENOBUFS) 239 retval = 0; 240 } else 241 retval = -ENOMEM; 242 } 243 #endif 244 245 /* call uevent_helper, usually only enabled during early boot */ 246 if (uevent_helper[0]) { 247 char *argv [3]; 248 249 argv [0] = uevent_helper; 250 argv [1] = (char *)subsystem; 251 argv [2] = NULL; 252 retval = add_uevent_var(env, "HOME=/"); 253 if (retval) 254 goto exit; 255 retval = add_uevent_var(env, 256 "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 257 if (retval) 258 goto exit; 259 260 retval = call_usermodehelper(argv[0], argv, 261 env->envp, UMH_NO_WAIT); 262 } 263 264 exit: 265 kfree(devpath); 266 kfree(env); 267 return retval; 268 } 269 EXPORT_SYMBOL_GPL(kobject_uevent_env); 270 271 /** 272 * kobject_uevent - notify userspace by ending an uevent 273 * 274 * @action: action that is happening 275 * @kobj: struct kobject that the action is happening to 276 * 277 * Returns 0 if kobject_uevent() is completed with success or the 278 * corresponding error when it fails. 279 */ 280 int kobject_uevent(struct kobject *kobj, enum kobject_action action) 281 { 282 return kobject_uevent_env(kobj, action, NULL); 283 } 284 EXPORT_SYMBOL_GPL(kobject_uevent); 285 286 /** 287 * add_uevent_var - add key value string to the environment buffer 288 * @env: environment buffer structure 289 * @format: printf format for the key=value pair 290 * 291 * Returns 0 if environment variable was added successfully or -ENOMEM 292 * if no space was available. 293 */ 294 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) 295 { 296 va_list args; 297 int len; 298 299 if (env->envp_idx >= ARRAY_SIZE(env->envp)) { 300 WARN(1, KERN_ERR "add_uevent_var: too many keys\n"); 301 return -ENOMEM; 302 } 303 304 va_start(args, format); 305 len = vsnprintf(&env->buf[env->buflen], 306 sizeof(env->buf) - env->buflen, 307 format, args); 308 va_end(args); 309 310 if (len >= (sizeof(env->buf) - env->buflen)) { 311 WARN(1, KERN_ERR "add_uevent_var: buffer size too small\n"); 312 return -ENOMEM; 313 } 314 315 env->envp[env->envp_idx++] = &env->buf[env->buflen]; 316 env->buflen += len + 1; 317 return 0; 318 } 319 EXPORT_SYMBOL_GPL(add_uevent_var); 320 321 #if defined(CONFIG_NET) 322 static int __init kobject_uevent_init(void) 323 { 324 uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, 325 1, NULL, NULL, THIS_MODULE); 326 if (!uevent_sock) { 327 printk(KERN_ERR 328 "kobject_uevent: unable to create netlink socket!\n"); 329 return -ENODEV; 330 } 331 332 return 0; 333 } 334 335 postcore_initcall(kobject_uevent_init); 336 #endif 337