diff options
Diffstat (limited to 'kernel/umh.c')
-rw-r--r-- | kernel/umh.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/kernel/umh.c b/kernel/umh.c index 0baa672e023c..d937cbad903a 100644 --- a/kernel/umh.c +++ b/kernel/umh.c | |||
@@ -37,6 +37,8 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; | |||
37 | static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; | 37 | static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; |
38 | static DEFINE_SPINLOCK(umh_sysctl_lock); | 38 | static DEFINE_SPINLOCK(umh_sysctl_lock); |
39 | static DECLARE_RWSEM(umhelper_sem); | 39 | static DECLARE_RWSEM(umhelper_sem); |
40 | static LIST_HEAD(umh_list); | ||
41 | static DEFINE_MUTEX(umh_list_lock); | ||
40 | 42 | ||
41 | static void call_usermodehelper_freeinfo(struct subprocess_info *info) | 43 | static void call_usermodehelper_freeinfo(struct subprocess_info *info) |
42 | { | 44 | { |
@@ -100,10 +102,12 @@ static int call_usermodehelper_exec_async(void *data) | |||
100 | commit_creds(new); | 102 | commit_creds(new); |
101 | 103 | ||
102 | sub_info->pid = task_pid_nr(current); | 104 | sub_info->pid = task_pid_nr(current); |
103 | if (sub_info->file) | 105 | if (sub_info->file) { |
104 | retval = do_execve_file(sub_info->file, | 106 | retval = do_execve_file(sub_info->file, |
105 | sub_info->argv, sub_info->envp); | 107 | sub_info->argv, sub_info->envp); |
106 | else | 108 | if (!retval) |
109 | current->flags |= PF_UMH; | ||
110 | } else | ||
107 | retval = do_execve(getname_kernel(sub_info->path), | 111 | retval = do_execve(getname_kernel(sub_info->path), |
108 | (const char __user *const __user *)sub_info->argv, | 112 | (const char __user *const __user *)sub_info->argv, |
109 | (const char __user *const __user *)sub_info->envp); | 113 | (const char __user *const __user *)sub_info->envp); |
@@ -517,6 +521,11 @@ int fork_usermode_blob(void *data, size_t len, struct umh_info *info) | |||
517 | goto out; | 521 | goto out; |
518 | 522 | ||
519 | err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); | 523 | err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); |
524 | if (!err) { | ||
525 | mutex_lock(&umh_list_lock); | ||
526 | list_add(&info->list, &umh_list); | ||
527 | mutex_unlock(&umh_list_lock); | ||
528 | } | ||
520 | out: | 529 | out: |
521 | fput(file); | 530 | fput(file); |
522 | return err; | 531 | return err; |
@@ -679,6 +688,26 @@ static int proc_cap_handler(struct ctl_table *table, int write, | |||
679 | return 0; | 688 | return 0; |
680 | } | 689 | } |
681 | 690 | ||
691 | void __exit_umh(struct task_struct *tsk) | ||
692 | { | ||
693 | struct umh_info *info; | ||
694 | pid_t pid = tsk->pid; | ||
695 | |||
696 | mutex_lock(&umh_list_lock); | ||
697 | list_for_each_entry(info, &umh_list, list) { | ||
698 | if (info->pid == pid) { | ||
699 | list_del(&info->list); | ||
700 | mutex_unlock(&umh_list_lock); | ||
701 | goto out; | ||
702 | } | ||
703 | } | ||
704 | mutex_unlock(&umh_list_lock); | ||
705 | return; | ||
706 | out: | ||
707 | if (info->cleanup) | ||
708 | info->cleanup(info); | ||
709 | } | ||
710 | |||
682 | struct ctl_table usermodehelper_table[] = { | 711 | struct ctl_table usermodehelper_table[] = { |
683 | { | 712 | { |
684 | .procname = "bset", | 713 | .procname = "bset", |