Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

umd: Transform fork_usermode_blob into fork_usermode_driver

Instead of loading a binary blob into a temporary file with
shmem_kernel_file_setup load a binary blob into a temporary tmpfs
filesystem. This means that the blob can be stored in an init section
and discared, and it means the binary blob will have a filename so can
be executed normally.

The only tricky thing about this code is that in the helper function
blob_to_mnt __fput_sync is used. That is because a file can not be
executed if it is still open for write, and the ordinary delayed close
for kernel threads does not happen soon enough, which causes the
following exec to fail. The function umd_load_blob is not called with
any locks so this should be safe.

Executing the blob normally winds up correcting several problems with
the user mode driver code discovered by Tetsuo Handa[1]. By passing
an ordinary filename into the exec, it is no longer necessary to
figure out how to turn a O_RDWR file descriptor into a properly
referende counted O_EXEC file descriptor that forbids all writes. For
path based LSMs there are no new special cases.

[1] https://lore.kernel.org/linux-fsdevel/2a8775b4-1dd5-9d5c-aa42-9872445e0942@i-love.sakura.ne.jp/
v1: https://lkml.kernel.org/r/87d05mf0j9.fsf_-_@x220.int.ebiederm.org
v2: https://lkml.kernel.org/r/87wo3p4p35.fsf_-_@x220.int.ebiederm.org
Link: https://lkml.kernel.org/r/20200702164140.4468-8-ebiederm@xmission.com
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Tested-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+113 -33
+5 -1
include/linux/usermode_driver.h
··· 2 2 #define __LINUX_USERMODE_DRIVER_H__ 3 3 4 4 #include <linux/umh.h> 5 + #include <linux/path.h> 5 6 6 7 #ifdef CONFIG_BPFILTER 7 8 void __exit_umh(struct task_struct *tsk); ··· 24 23 struct file *pipe_from_umh; 25 24 struct list_head list; 26 25 void (*cleanup)(struct umd_info *info); 26 + struct path wd; 27 27 pid_t pid; 28 28 }; 29 - int fork_usermode_blob(void *data, size_t len, struct umd_info *info); 29 + int umd_load_blob(struct umd_info *info, const void *data, size_t len); 30 + int umd_unload_blob(struct umd_info *info); 31 + int fork_usermode_driver(struct umd_info *info); 30 32 31 33 #endif /* __LINUX_USERMODE_DRIVER_H__ */
+97 -29
kernel/usermode_driver.c
··· 4 4 */ 5 5 #include <linux/shmem_fs.h> 6 6 #include <linux/pipe_fs_i.h> 7 + #include <linux/mount.h> 8 + #include <linux/fs_struct.h> 9 + #include <linux/task_work.h> 7 10 #include <linux/usermode_driver.h> 8 11 9 12 static LIST_HEAD(umh_list); 10 13 static DEFINE_MUTEX(umh_list_lock); 14 + 15 + static 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 + */ 63 + int 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 + } 78 + EXPORT_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 + */ 85 + int 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 + } 97 + EXPORT_SYMBOL_GPL(umd_unload_blob); 11 98 12 99 static int umd_setup(struct subprocess_info *info, struct cred *new) 13 100 { ··· 130 43 return err; 131 44 } 132 45 46 + set_fs_pwd(current->fs, &umd_info->wd); 133 47 umd_info->pipe_to_umh = to_umh[1]; 134 48 umd_info->pipe_from_umh = from_umh[0]; 135 49 umd_info->pid = task_pid_nr(current); ··· 150 62 } 151 63 152 64 /** 153 - * fork_usermode_blob - fork a blob of bytes as a usermode process 154 - * @data: a blob of bytes that can be do_execv-ed as a file 155 - * @len: length of the blob 156 - * @info: information about usermode process (shouldn't be NULL) 65 + * fork_usermode_driver - fork a usermode driver 66 + * @info: information about usermode driver (shouldn't be NULL) 157 67 * 158 - * Returns either negative error or zero which indicates success 159 - * in executing a blob of bytes as a usermode process. In such 160 - * case 'struct umd_info *info' is populated with two pipes 161 - * and a pid of the process. The caller is responsible for health 162 - * check of the user process, killing it via pid, and closing the 163 - * pipes when user process is no longer needed. 68 + * Returns either negative error or zero which indicates success in 69 + * executing a usermode driver. In such case 'struct umd_info *info' 70 + * is populated with two pipes and a pid of the process. The caller is 71 + * responsible for health check of the user process, killing it via 72 + * pid, and closing the pipes when user process is no longer needed. 164 73 */ 165 - int fork_usermode_blob(void *data, size_t len, struct umd_info *info) 74 + int fork_usermode_driver(struct umd_info *info) 166 75 { 167 76 struct subprocess_info *sub_info; 168 77 char **argv = NULL; 169 - struct file *file; 170 - ssize_t written; 171 - loff_t pos = 0; 172 78 int err; 173 - 174 - file = shmem_kernel_file_setup(info->driver_name, len, 0); 175 - if (IS_ERR(file)) 176 - return PTR_ERR(file); 177 - 178 - written = kernel_write(file, data, len, &pos); 179 - if (written != len) { 180 - err = written; 181 - if (err >= 0) 182 - err = -ENOMEM; 183 - goto out; 184 - } 185 79 186 80 err = -ENOMEM; 187 81 argv = argv_split(GFP_KERNEL, info->driver_name, NULL); ··· 176 106 if (!sub_info) 177 107 goto out; 178 108 179 - sub_info->file = file; 180 109 err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC); 181 110 if (!err) { 182 111 mutex_lock(&umh_list_lock); ··· 185 116 out: 186 117 if (argv) 187 118 argv_free(argv); 188 - fput(file); 189 119 return err; 190 120 } 191 - EXPORT_SYMBOL_GPL(fork_usermode_blob); 121 + EXPORT_SYMBOL_GPL(fork_usermode_driver); 192 122 193 123 void __exit_umh(struct task_struct *tsk) 194 124 {
+11 -3
net/bpfilter/bpfilter_kern.c
··· 77 77 int err; 78 78 79 79 /* fork usermode process */ 80 - err = fork_usermode_blob(&bpfilter_umh_start, 81 - &bpfilter_umh_end - &bpfilter_umh_start, 82 - &bpfilter_ops.info); 80 + err = fork_usermode_driver(&bpfilter_ops.info); 83 81 if (err) 84 82 return err; 85 83 bpfilter_ops.stop = false; ··· 96 98 { 97 99 int err; 98 100 101 + err = umd_load_blob(&bpfilter_ops.info, 102 + &bpfilter_umh_start, 103 + &bpfilter_umh_end - &bpfilter_umh_start); 104 + if (err) 105 + return err; 106 + 99 107 mutex_lock(&bpfilter_ops.lock); 100 108 if (!bpfilter_ops.stop) { 101 109 err = -EFAULT; ··· 114 110 } 115 111 out: 116 112 mutex_unlock(&bpfilter_ops.lock); 113 + if (err) 114 + umd_unload_blob(&bpfilter_ops.info); 117 115 return err; 118 116 } 119 117 ··· 128 122 bpfilter_ops.sockopt = NULL; 129 123 } 130 124 mutex_unlock(&bpfilter_ops.lock); 125 + 126 + umd_unload_blob(&bpfilter_ops.info); 131 127 } 132 128 module_init(load_umh); 133 129 module_exit(fini_umh);