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", |
