bpfilter: Move bpfilter_umh back into init data
[linux-block.git] / kernel / usermode_driver.c
CommitLineData
884c5e68
EB
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>
e2dc9bf3
EB
7#include <linux/mount.h>
8#include <linux/fs_struct.h>
9#include <linux/task_work.h>
884c5e68
EB
10#include <linux/usermode_driver.h>
11
12static LIST_HEAD(umh_list);
13static DEFINE_MUTEX(umh_list_lock);
14
e2dc9bf3
EB
15static struct vfsmount *blob_to_mnt(const void *data, size_t len, const char *name)
16{
17 struct file_system_type *type;
18 struct vfsmount *mnt;
19 struct file *file;
20 ssize_t written;
21 loff_t pos = 0;
22
23 type = get_fs_type("tmpfs");
24 if (!type)
25 return ERR_PTR(-ENODEV);
26
27 mnt = kern_mount(type);
28 put_filesystem(type);
29 if (IS_ERR(mnt))
30 return mnt;
31
32 file = file_open_root(mnt->mnt_root, mnt, name, O_CREAT | O_WRONLY, 0700);
33 if (IS_ERR(file)) {
34 mntput(mnt);
35 return ERR_CAST(file);
36 }
37
38 written = kernel_write(file, data, len, &pos);
39 if (written != len) {
40 int err = written;
41 if (err >= 0)
42 err = -ENOMEM;
43 filp_close(file, NULL);
44 mntput(mnt);
45 return ERR_PTR(err);
46 }
47
48 fput(file);
49
50 /* Flush delayed fput so exec can open the file read-only */
51 flush_delayed_fput();
52 task_work_run();
53 return mnt;
54}
55
56/**
57 * umd_load_blob - Remember a blob of bytes for fork_usermode_driver
58 * @info: information about usermode driver
59 * @data: a blob of bytes that can be executed as a file
60 * @len: The lentgh of the blob
61 *
62 */
63int umd_load_blob(struct umd_info *info, const void *data, size_t len)
64{
65 struct vfsmount *mnt;
66
67 if (WARN_ON_ONCE(info->wd.dentry || info->wd.mnt))
68 return -EBUSY;
69
70 mnt = blob_to_mnt(data, len, info->driver_name);
71 if (IS_ERR(mnt))
72 return PTR_ERR(mnt);
73
74 info->wd.mnt = mnt;
75 info->wd.dentry = mnt->mnt_root;
76 return 0;
77}
78EXPORT_SYMBOL_GPL(umd_load_blob);
79
80/**
81 * umd_unload_blob - Disassociate @info from a previously loaded blob
82 * @info: information about usermode driver
83 *
84 */
85int umd_unload_blob(struct umd_info *info)
86{
87 if (WARN_ON_ONCE(!info->wd.mnt ||
88 !info->wd.dentry ||
89 info->wd.mnt->mnt_root != info->wd.dentry))
90 return -EINVAL;
91
92 kern_unmount(info->wd.mnt);
93 info->wd.mnt = NULL;
94 info->wd.dentry = NULL;
95 return 0;
96}
97EXPORT_SYMBOL_GPL(umd_unload_blob);
98
884c5e68
EB
99static int umd_setup(struct subprocess_info *info, struct cred *new)
100{
74be2d3b 101 struct umd_info *umd_info = info->data;
884c5e68
EB
102 struct file *from_umh[2];
103 struct file *to_umh[2];
104 int err;
105
106 /* create pipe to send data to umh */
107 err = create_pipe_files(to_umh, 0);
108 if (err)
109 return err;
110 err = replace_fd(0, to_umh[0], 0);
111 fput(to_umh[0]);
112 if (err < 0) {
113 fput(to_umh[1]);
114 return err;
115 }
116
117 /* create pipe to receive data from umh */
118 err = create_pipe_files(from_umh, 0);
119 if (err) {
120 fput(to_umh[1]);
121 replace_fd(0, NULL, 0);
122 return err;
123 }
124 err = replace_fd(1, from_umh[1], 0);
125 fput(from_umh[1]);
126 if (err < 0) {
127 fput(to_umh[1]);
128 replace_fd(0, NULL, 0);
129 fput(from_umh[0]);
130 return err;
131 }
132
e2dc9bf3 133 set_fs_pwd(current->fs, &umd_info->wd);
74be2d3b
EB
134 umd_info->pipe_to_umh = to_umh[1];
135 umd_info->pipe_from_umh = from_umh[0];
136 umd_info->pid = task_pid_nr(current);
884c5e68
EB
137 current->flags |= PF_UMH;
138 return 0;
139}
140
141static void umd_cleanup(struct subprocess_info *info)
142{
74be2d3b 143 struct umd_info *umd_info = info->data;
884c5e68
EB
144
145 /* cleanup if umh_setup() was successful but exec failed */
146 if (info->retval) {
74be2d3b
EB
147 fput(umd_info->pipe_to_umh);
148 fput(umd_info->pipe_from_umh);
884c5e68
EB
149 }
150}
151
152/**
e2dc9bf3
EB
153 * fork_usermode_driver - fork a usermode driver
154 * @info: information about usermode driver (shouldn't be NULL)
884c5e68 155 *
e2dc9bf3
EB
156 * Returns either negative error or zero which indicates success in
157 * executing a usermode driver. In such case 'struct umd_info *info'
158 * is populated with two pipes and a pid of the process. The caller is
159 * responsible for health check of the user process, killing it via
160 * pid, and closing the pipes when user process is no longer needed.
884c5e68 161 */
e2dc9bf3 162int fork_usermode_driver(struct umd_info *info)
884c5e68 163{
884c5e68
EB
164 struct subprocess_info *sub_info;
165 char **argv = NULL;
884c5e68
EB
166 int err;
167
884c5e68 168 err = -ENOMEM;
1199c6c3 169 argv = argv_split(GFP_KERNEL, info->driver_name, NULL);
884c5e68
EB
170 if (!argv)
171 goto out;
172
1199c6c3
EB
173 sub_info = call_usermodehelper_setup(info->driver_name, argv, NULL,
174 GFP_KERNEL,
884c5e68
EB
175 umd_setup, umd_cleanup, info);
176 if (!sub_info)
177 goto out;
178
884c5e68
EB
179 err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
180 if (!err) {
181 mutex_lock(&umh_list_lock);
182 list_add(&info->list, &umh_list);
183 mutex_unlock(&umh_list_lock);
184 }
185out:
186 if (argv)
187 argv_free(argv);
884c5e68
EB
188 return err;
189}
e2dc9bf3 190EXPORT_SYMBOL_GPL(fork_usermode_driver);
884c5e68
EB
191
192void __exit_umh(struct task_struct *tsk)
193{
74be2d3b 194 struct umd_info *info;
884c5e68
EB
195 pid_t pid = tsk->pid;
196
197 mutex_lock(&umh_list_lock);
198 list_for_each_entry(info, &umh_list, list) {
199 if (info->pid == pid) {
200 list_del(&info->list);
201 mutex_unlock(&umh_list_lock);
202 goto out;
203 }
204 }
205 mutex_unlock(&umh_list_lock);
206 return;
207out:
208 if (info->cleanup)
209 info->cleanup(info);
210}
211