aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaehee Yoo <ap420073@gmail.com>2019-01-08 12:23:56 -0500
committerDavid S. Miller <davem@davemloft.net>2019-01-11 21:05:40 -0500
commit73ab1cb2de9e3efe7f818d5453de271e5371df1d (patch)
tree597da57b75e0bceceea75e1cbf9980068bc5dc54
parent2ff33d6637393fe9348357285931811b76e1402f (diff)
umh: add exit routine for UMH process
A UMH process which is created by the fork_usermode_blob() such as bpfilter needs to release members of the umh_info when process is terminated. But the do_exit() does not release members of the umh_info. hence module which uses UMH needs own code to detect whether UMH process is terminated or not. But this implementation needs extra code for checking the status of UMH process. it eventually makes the code more complex. The new PF_UMH flag is added and it is used to identify UMH processes. The exit_umh() does not release members of the umh_info. Hence umh_info->cleanup callback should release both members of the umh_info and the private data. Suggested-by: David S. Miller <davem@davemloft.net> Signed-off-by: Taehee Yoo <ap420073@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/sched.h9
-rw-r--r--include/linux/umh.h2
-rw-r--r--kernel/exit.c1
-rw-r--r--kernel/umh.c33
4 files changed, 43 insertions, 2 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 89541d248893..e35e35b9fc48 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1406,6 +1406,7 @@ extern struct pid *cad_pid;
1406#define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */ 1406#define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */
1407#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ 1407#define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */
1408#define PF_MEMSTALL 0x01000000 /* Stalled due to lack of memory */ 1408#define PF_MEMSTALL 0x01000000 /* Stalled due to lack of memory */
1409#define PF_UMH 0x02000000 /* I'm an Usermodehelper process */
1409#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ 1410#define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */
1410#define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ 1411#define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */
1411#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ 1412#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */
@@ -1904,6 +1905,14 @@ static inline void rseq_execve(struct task_struct *t)
1904 1905
1905#endif 1906#endif
1906 1907
1908void __exit_umh(struct task_struct *tsk);
1909
1910static inline void exit_umh(struct task_struct *tsk)
1911{
1912 if (unlikely(tsk->flags & PF_UMH))
1913 __exit_umh(tsk);
1914}
1915
1907#ifdef CONFIG_DEBUG_RSEQ 1916#ifdef CONFIG_DEBUG_RSEQ
1908 1917
1909void rseq_syscall(struct pt_regs *regs); 1918void rseq_syscall(struct pt_regs *regs);
diff --git a/include/linux/umh.h b/include/linux/umh.h
index 235f51b62c71..0c08de356d0d 100644
--- a/include/linux/umh.h
+++ b/include/linux/umh.h
@@ -47,6 +47,8 @@ struct umh_info {
47 const char *cmdline; 47 const char *cmdline;
48 struct file *pipe_to_umh; 48 struct file *pipe_to_umh;
49 struct file *pipe_from_umh; 49 struct file *pipe_from_umh;
50 struct list_head list;
51 void (*cleanup)(struct umh_info *info);
50 pid_t pid; 52 pid_t pid;
51}; 53};
52int fork_usermode_blob(void *data, size_t len, struct umh_info *info); 54int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
diff --git a/kernel/exit.c b/kernel/exit.c
index 8a01b671dc1f..dad70419195c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -866,6 +866,7 @@ void __noreturn do_exit(long code)
866 exit_task_namespaces(tsk); 866 exit_task_namespaces(tsk);
867 exit_task_work(tsk); 867 exit_task_work(tsk);
868 exit_thread(tsk); 868 exit_thread(tsk);
869 exit_umh(tsk);
869 870
870 /* 871 /*
871 * Flush inherited counters to the parent - before the parent 872 * Flush inherited counters to the parent - before the parent
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;
37static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; 37static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
38static DEFINE_SPINLOCK(umh_sysctl_lock); 38static DEFINE_SPINLOCK(umh_sysctl_lock);
39static DECLARE_RWSEM(umhelper_sem); 39static DECLARE_RWSEM(umhelper_sem);
40static LIST_HEAD(umh_list);
41static DEFINE_MUTEX(umh_list_lock);
40 42
41static void call_usermodehelper_freeinfo(struct subprocess_info *info) 43static 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 }
520out: 529out:
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
691void __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;
706out:
707 if (info->cleanup)
708 info->cleanup(info);
709}
710
682struct ctl_table usermodehelper_table[] = { 711struct ctl_table usermodehelper_table[] = {
683 { 712 {
684 .procname = "bset", 713 .procname = "bset",