aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kobject_uevent.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2014-06-08 02:24:07 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-06-08 02:24:07 -0400
commita292241cccb7e20e8b997a9a44177e7c98141859 (patch)
treea0b0bb95e7dce3233a2d8b203f9e326cdec7a00e /lib/kobject_uevent.c
parentd49cb7aeebb974713f9f7ab2991352d3050b095b (diff)
parent68807a0c2015cb40df4869e16651f0ce5cc14d52 (diff)
Merge branch 'next' into for-linus
Prepare input updates for 3.16.
Diffstat (limited to 'lib/kobject_uevent.c')
-rw-r--r--lib/kobject_uevent.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 5f72767ddd9b..4e3bd71bd949 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -124,6 +124,30 @@ static int kobj_usermode_filter(struct kobject *kobj)
124 return 0; 124 return 0;
125} 125}
126 126
127static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
128{
129 int len;
130
131 len = strlcpy(&env->buf[env->buflen], subsystem,
132 sizeof(env->buf) - env->buflen);
133 if (len >= (sizeof(env->buf) - env->buflen)) {
134 WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
135 return -ENOMEM;
136 }
137
138 env->argv[0] = uevent_helper;
139 env->argv[1] = &env->buf[env->buflen];
140 env->argv[2] = NULL;
141
142 env->buflen += len + 1;
143 return 0;
144}
145
146static void cleanup_uevent_env(struct subprocess_info *info)
147{
148 kfree(info->data);
149}
150
127/** 151/**
128 * kobject_uevent_env - send an uevent with environmental data 152 * kobject_uevent_env - send an uevent with environmental data
129 * 153 *
@@ -301,11 +325,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
301 325
302 /* call uevent_helper, usually only enabled during early boot */ 326 /* call uevent_helper, usually only enabled during early boot */
303 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { 327 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
304 char *argv [3]; 328 struct subprocess_info *info;
305 329
306 argv [0] = uevent_helper;
307 argv [1] = (char *)subsystem;
308 argv [2] = NULL;
309 retval = add_uevent_var(env, "HOME=/"); 330 retval = add_uevent_var(env, "HOME=/");
310 if (retval) 331 if (retval)
311 goto exit; 332 goto exit;
@@ -313,9 +334,18 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
313 "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); 334 "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
314 if (retval) 335 if (retval)
315 goto exit; 336 goto exit;
337 retval = init_uevent_argv(env, subsystem);
338 if (retval)
339 goto exit;
316 340
317 retval = call_usermodehelper(argv[0], argv, 341 retval = -ENOMEM;
318 env->envp, UMH_WAIT_EXEC); 342 info = call_usermodehelper_setup(env->argv[0], env->argv,
343 env->envp, GFP_KERNEL,
344 NULL, cleanup_uevent_env, env);
345 if (info) {
346 retval = call_usermodehelper_exec(info, UMH_NO_WAIT);
347 env = NULL; /* freed by cleanup_uevent_env */
348 }
319 } 349 }
320 350
321exit: 351exit: