0001
0002 #include <linux/fs.h>
0003 #include <linux/fs_struct.h>
0004 #include <linux/kernel_read_file.h>
0005 #include <linux/security.h>
0006 #include <linux/vmalloc.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 ssize_t kernel_read_file(struct file *file, loff_t offset, void **buf,
0036 size_t buf_size, size_t *file_size,
0037 enum kernel_read_file_id id)
0038 {
0039 loff_t i_size, pos;
0040 ssize_t copied;
0041 void *allocated = NULL;
0042 bool whole_file;
0043 int ret;
0044
0045 if (offset != 0 && (!*buf || !file_size))
0046 return -EINVAL;
0047
0048 if (!S_ISREG(file_inode(file)->i_mode))
0049 return -EINVAL;
0050
0051 ret = deny_write_access(file);
0052 if (ret)
0053 return ret;
0054
0055 i_size = i_size_read(file_inode(file));
0056 if (i_size <= 0) {
0057 ret = -EINVAL;
0058 goto out;
0059 }
0060
0061 if (i_size > SSIZE_MAX) {
0062 ret = -EFBIG;
0063 goto out;
0064 }
0065
0066 if (!file_size && offset == 0 && i_size > buf_size) {
0067 ret = -EFBIG;
0068 goto out;
0069 }
0070
0071 whole_file = (offset == 0 && i_size <= buf_size);
0072 ret = security_kernel_read_file(file, id, whole_file);
0073 if (ret)
0074 goto out;
0075
0076 if (file_size)
0077 *file_size = i_size;
0078
0079 if (!*buf)
0080 *buf = allocated = vmalloc(i_size);
0081 if (!*buf) {
0082 ret = -ENOMEM;
0083 goto out;
0084 }
0085
0086 pos = offset;
0087 copied = 0;
0088 while (copied < buf_size) {
0089 ssize_t bytes;
0090 size_t wanted = min_t(size_t, buf_size - copied,
0091 i_size - pos);
0092
0093 bytes = kernel_read(file, *buf + copied, wanted, &pos);
0094 if (bytes < 0) {
0095 ret = bytes;
0096 goto out_free;
0097 }
0098
0099 if (bytes == 0)
0100 break;
0101 copied += bytes;
0102 }
0103
0104 if (whole_file) {
0105 if (pos != i_size) {
0106 ret = -EIO;
0107 goto out_free;
0108 }
0109
0110 ret = security_kernel_post_read_file(file, *buf, i_size, id);
0111 }
0112
0113 out_free:
0114 if (ret < 0) {
0115 if (allocated) {
0116 vfree(*buf);
0117 *buf = NULL;
0118 }
0119 }
0120
0121 out:
0122 allow_write_access(file);
0123 return ret == 0 ? copied : ret;
0124 }
0125 EXPORT_SYMBOL_GPL(kernel_read_file);
0126
0127 ssize_t kernel_read_file_from_path(const char *path, loff_t offset, void **buf,
0128 size_t buf_size, size_t *file_size,
0129 enum kernel_read_file_id id)
0130 {
0131 struct file *file;
0132 ssize_t ret;
0133
0134 if (!path || !*path)
0135 return -EINVAL;
0136
0137 file = filp_open(path, O_RDONLY, 0);
0138 if (IS_ERR(file))
0139 return PTR_ERR(file);
0140
0141 ret = kernel_read_file(file, offset, buf, buf_size, file_size, id);
0142 fput(file);
0143 return ret;
0144 }
0145 EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
0146
0147 ssize_t kernel_read_file_from_path_initns(const char *path, loff_t offset,
0148 void **buf, size_t buf_size,
0149 size_t *file_size,
0150 enum kernel_read_file_id id)
0151 {
0152 struct file *file;
0153 struct path root;
0154 ssize_t ret;
0155
0156 if (!path || !*path)
0157 return -EINVAL;
0158
0159 task_lock(&init_task);
0160 get_fs_root(init_task.fs, &root);
0161 task_unlock(&init_task);
0162
0163 file = file_open_root(&root, path, O_RDONLY, 0);
0164 path_put(&root);
0165 if (IS_ERR(file))
0166 return PTR_ERR(file);
0167
0168 ret = kernel_read_file(file, offset, buf, buf_size, file_size, id);
0169 fput(file);
0170 return ret;
0171 }
0172 EXPORT_SYMBOL_GPL(kernel_read_file_from_path_initns);
0173
0174 ssize_t kernel_read_file_from_fd(int fd, loff_t offset, void **buf,
0175 size_t buf_size, size_t *file_size,
0176 enum kernel_read_file_id id)
0177 {
0178 struct fd f = fdget(fd);
0179 ssize_t ret = -EBADF;
0180
0181 if (!f.file || !(f.file->f_mode & FMODE_READ))
0182 goto out;
0183
0184 ret = kernel_read_file(f.file, offset, buf, buf_size, file_size, id);
0185 out:
0186 fdput(f);
0187 return ret;
0188 }
0189 EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);