diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-06-08 02:24:07 -0400 |
| commit | a292241cccb7e20e8b997a9a44177e7c98141859 (patch) | |
| tree | a0b0bb95e7dce3233a2d8b203f9e326cdec7a00e /lib/kobject_uevent.c | |
| parent | d49cb7aeebb974713f9f7ab2991352d3050b095b (diff) | |
| parent | 68807a0c2015cb40df4869e16651f0ce5cc14d52 (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.c | 42 |
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 | ||
| 127 | static 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 | |||
| 146 | static 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 | ||
| 321 | exit: | 351 | exit: |
