xref: /linux-6.15/kernel/usermode_driver.c (revision 74be2d3b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * umd - User mode driver support
4  */
5 #include <linux/shmem_fs.h>
6 #include <linux/pipe_fs_i.h>
7 #include <linux/usermode_driver.h>
8 
9 static LIST_HEAD(umh_list);
10 static DEFINE_MUTEX(umh_list_lock);
11 
12 static int umd_setup(struct subprocess_info *info, struct cred *new)
13 {
14 	struct umd_info *umd_info = info->data;
15 	struct file *from_umh[2];
16 	struct file *to_umh[2];
17 	int err;
18 
19 	/* create pipe to send data to umh */
20 	err = create_pipe_files(to_umh, 0);
21 	if (err)
22 		return err;
23 	err = replace_fd(0, to_umh[0], 0);
24 	fput(to_umh[0]);
25 	if (err < 0) {
26 		fput(to_umh[1]);
27 		return err;
28 	}
29 
30 	/* create pipe to receive data from umh */
31 	err = create_pipe_files(from_umh, 0);
32 	if (err) {
33 		fput(to_umh[1]);
34 		replace_fd(0, NULL, 0);
35 		return err;
36 	}
37 	err = replace_fd(1, from_umh[1], 0);
38 	fput(from_umh[1]);
39 	if (err < 0) {
40 		fput(to_umh[1]);
41 		replace_fd(0, NULL, 0);
42 		fput(from_umh[0]);
43 		return err;
44 	}
45 
46 	umd_info->pipe_to_umh = to_umh[1];
47 	umd_info->pipe_from_umh = from_umh[0];
48 	umd_info->pid = task_pid_nr(current);
49 	current->flags |= PF_UMH;
50 	return 0;
51 }
52 
53 static void umd_cleanup(struct subprocess_info *info)
54 {
55 	struct umd_info *umd_info = info->data;
56 
57 	/* cleanup if umh_setup() was successful but exec failed */
58 	if (info->retval) {
59 		fput(umd_info->pipe_to_umh);
60 		fput(umd_info->pipe_from_umh);
61 	}
62 }
63 
64 /**
65  * fork_usermode_blob - fork a blob of bytes as a usermode process
66  * @data: a blob of bytes that can be do_execv-ed as a file
67  * @len: length of the blob
68  * @info: information about usermode process (shouldn't be NULL)
69  *
70  * If info->cmdline is set it will be used as command line for the
71  * user process, else "usermodehelper" is used.
72  *
73  * Returns either negative error or zero which indicates success
74  * in executing a blob of bytes as a usermode process. In such
75  * case 'struct umd_info *info' is populated with two pipes
76  * and a pid of the process. The caller is responsible for health
77  * check of the user process, killing it via pid, and closing the
78  * pipes when user process is no longer needed.
79  */
80 int fork_usermode_blob(void *data, size_t len, struct umd_info *info)
81 {
82 	const char *cmdline = (info->cmdline) ? info->cmdline : "usermodehelper";
83 	struct subprocess_info *sub_info;
84 	char **argv = NULL;
85 	struct file *file;
86 	ssize_t written;
87 	loff_t pos = 0;
88 	int err;
89 
90 	file = shmem_kernel_file_setup("", len, 0);
91 	if (IS_ERR(file))
92 		return PTR_ERR(file);
93 
94 	written = kernel_write(file, data, len, &pos);
95 	if (written != len) {
96 		err = written;
97 		if (err >= 0)
98 			err = -ENOMEM;
99 		goto out;
100 	}
101 
102 	err = -ENOMEM;
103 	argv = argv_split(GFP_KERNEL, cmdline, NULL);
104 	if (!argv)
105 		goto out;
106 
107 	sub_info = call_usermodehelper_setup("none", argv, NULL, GFP_KERNEL,
108 					     umd_setup, umd_cleanup, info);
109 	if (!sub_info)
110 		goto out;
111 
112 	sub_info->file = file;
113 	err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
114 	if (!err) {
115 		mutex_lock(&umh_list_lock);
116 		list_add(&info->list, &umh_list);
117 		mutex_unlock(&umh_list_lock);
118 	}
119 out:
120 	if (argv)
121 		argv_free(argv);
122 	fput(file);
123 	return err;
124 }
125 EXPORT_SYMBOL_GPL(fork_usermode_blob);
126 
127 void __exit_umh(struct task_struct *tsk)
128 {
129 	struct umd_info *info;
130 	pid_t pid = tsk->pid;
131 
132 	mutex_lock(&umh_list_lock);
133 	list_for_each_entry(info, &umh_list, list) {
134 		if (info->pid == pid) {
135 			list_del(&info->list);
136 			mutex_unlock(&umh_list_lock);
137 			goto out;
138 		}
139 	}
140 	mutex_unlock(&umh_list_lock);
141 	return;
142 out:
143 	if (info->cleanup)
144 		info->cleanup(info);
145 }
146 
147