0001
0002
0003
0004
0005 #include <linux/shmem_fs.h>
0006 #include <linux/pipe_fs_i.h>
0007 #include <linux/mount.h>
0008 #include <linux/fs_struct.h>
0009 #include <linux/task_work.h>
0010 #include <linux/usermode_driver.h>
0011
0012 static struct vfsmount *blob_to_mnt(const void *data, size_t len, const char *name)
0013 {
0014 struct file_system_type *type;
0015 struct vfsmount *mnt;
0016 struct file *file;
0017 ssize_t written;
0018 loff_t pos = 0;
0019
0020 type = get_fs_type("tmpfs");
0021 if (!type)
0022 return ERR_PTR(-ENODEV);
0023
0024 mnt = kern_mount(type);
0025 put_filesystem(type);
0026 if (IS_ERR(mnt))
0027 return mnt;
0028
0029 file = file_open_root_mnt(mnt, name, O_CREAT | O_WRONLY, 0700);
0030 if (IS_ERR(file)) {
0031 kern_unmount(mnt);
0032 return ERR_CAST(file);
0033 }
0034
0035 written = kernel_write(file, data, len, &pos);
0036 if (written != len) {
0037 int err = written;
0038 if (err >= 0)
0039 err = -ENOMEM;
0040 filp_close(file, NULL);
0041 kern_unmount(mnt);
0042 return ERR_PTR(err);
0043 }
0044
0045 fput(file);
0046
0047
0048 flush_delayed_fput();
0049 task_work_run();
0050 return mnt;
0051 }
0052
0053
0054
0055
0056
0057
0058
0059
0060 int umd_load_blob(struct umd_info *info, const void *data, size_t len)
0061 {
0062 struct vfsmount *mnt;
0063
0064 if (WARN_ON_ONCE(info->wd.dentry || info->wd.mnt))
0065 return -EBUSY;
0066
0067 mnt = blob_to_mnt(data, len, info->driver_name);
0068 if (IS_ERR(mnt))
0069 return PTR_ERR(mnt);
0070
0071 info->wd.mnt = mnt;
0072 info->wd.dentry = mnt->mnt_root;
0073 return 0;
0074 }
0075 EXPORT_SYMBOL_GPL(umd_load_blob);
0076
0077
0078
0079
0080
0081
0082 int umd_unload_blob(struct umd_info *info)
0083 {
0084 if (WARN_ON_ONCE(!info->wd.mnt ||
0085 !info->wd.dentry ||
0086 info->wd.mnt->mnt_root != info->wd.dentry))
0087 return -EINVAL;
0088
0089 kern_unmount(info->wd.mnt);
0090 info->wd.mnt = NULL;
0091 info->wd.dentry = NULL;
0092 return 0;
0093 }
0094 EXPORT_SYMBOL_GPL(umd_unload_blob);
0095
0096 static int umd_setup(struct subprocess_info *info, struct cred *new)
0097 {
0098 struct umd_info *umd_info = info->data;
0099 struct file *from_umh[2];
0100 struct file *to_umh[2];
0101 int err;
0102
0103
0104 err = create_pipe_files(to_umh, 0);
0105 if (err)
0106 return err;
0107 err = replace_fd(0, to_umh[0], 0);
0108 fput(to_umh[0]);
0109 if (err < 0) {
0110 fput(to_umh[1]);
0111 return err;
0112 }
0113
0114
0115 err = create_pipe_files(from_umh, 0);
0116 if (err) {
0117 fput(to_umh[1]);
0118 replace_fd(0, NULL, 0);
0119 return err;
0120 }
0121 err = replace_fd(1, from_umh[1], 0);
0122 fput(from_umh[1]);
0123 if (err < 0) {
0124 fput(to_umh[1]);
0125 replace_fd(0, NULL, 0);
0126 fput(from_umh[0]);
0127 return err;
0128 }
0129
0130 set_fs_pwd(current->fs, &umd_info->wd);
0131 umd_info->pipe_to_umh = to_umh[1];
0132 umd_info->pipe_from_umh = from_umh[0];
0133 umd_info->tgid = get_pid(task_tgid(current));
0134 return 0;
0135 }
0136
0137 static void umd_cleanup(struct subprocess_info *info)
0138 {
0139 struct umd_info *umd_info = info->data;
0140
0141
0142 if (info->retval)
0143 umd_cleanup_helper(umd_info);
0144 }
0145
0146
0147
0148
0149
0150 void umd_cleanup_helper(struct umd_info *info)
0151 {
0152 fput(info->pipe_to_umh);
0153 fput(info->pipe_from_umh);
0154 put_pid(info->tgid);
0155 info->tgid = NULL;
0156 }
0157 EXPORT_SYMBOL_GPL(umd_cleanup_helper);
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 int fork_usermode_driver(struct umd_info *info)
0170 {
0171 struct subprocess_info *sub_info;
0172 const char *argv[] = { info->driver_name, NULL };
0173 int err;
0174
0175 if (WARN_ON_ONCE(info->tgid))
0176 return -EBUSY;
0177
0178 err = -ENOMEM;
0179 sub_info = call_usermodehelper_setup(info->driver_name,
0180 (char **)argv, NULL, GFP_KERNEL,
0181 umd_setup, umd_cleanup, info);
0182 if (!sub_info)
0183 goto out;
0184
0185 err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
0186 out:
0187 return err;
0188 }
0189 EXPORT_SYMBOL_GPL(fork_usermode_driver);
0190
0191