diff options
author | Paul Moore <pmoore@redhat.com> | 2014-06-17 17:30:23 -0400 |
---|---|---|
committer | Paul Moore <pmoore@redhat.com> | 2014-06-17 17:30:23 -0400 |
commit | 170b5910d9fbea79de1bb40df22eda5f98250c0c (patch) | |
tree | ca9560e878d2842d45c6f99077d0d8b8f8b0f9ba /lib/kobject_uevent.c | |
parent | 47dd0b76ace953bd2c0479076db0d3e3b9594003 (diff) | |
parent | 1860e379875dfe7271c649058aeddffe5afd9d0d (diff) |
Merge tag 'v3.15' into next
Linux 3.15
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 5f72767ddd9..4e3bd71bd94 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -124,6 +124,30 @@ static int kobj_usermode_filter(struct kobject *kobj) return 0; } +static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem) +{ + int len; + + len = strlcpy(&env->buf[env->buflen], subsystem, + sizeof(env->buf) - env->buflen); + if (len >= (sizeof(env->buf) - env->buflen)) { + WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n"); + return -ENOMEM; + } + + env->argv[0] = uevent_helper; + env->argv[1] = &env->buf[env->buflen]; + env->argv[2] = NULL; + + env->buflen += len + 1; + return 0; +} + +static void cleanup_uevent_env(struct subprocess_info *info) +{ + kfree(info->data); +} + /** * kobject_uevent_env - send an uevent with environmental data * @@ -301,11 +325,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, /* call uevent_helper, usually only enabled during early boot */ if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { - char *argv [3]; + struct subprocess_info *info; - argv [0] = uevent_helper; - argv [1] = (char *)subsystem; - argv [2] = NULL; retval = add_uevent_var(env, "HOME=/"); if (retval) goto exit; @@ -313,9 +334,18 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); if (retval) goto exit; + retval = init_uevent_argv(env, subsystem); + if (retval) + goto exit; - retval = call_usermodehelper(argv[0], argv, - env->envp, UMH_WAIT_EXEC); + retval = -ENOMEM; + info = call_usermodehelper_setup(env->argv[0], env->argv, + env->envp, GFP_KERNEL, + NULL, cleanup_uevent_env, env); + if (info) { + retval = call_usermodehelper_exec(info, UMH_NO_WAIT); + env = NULL; /* freed by cleanup_uevent_env */ + } } exit: |