Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
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  * kernel_read_file() - read file contents into a kernel buffer
0010  *
0011  * @file    file to read from
0012  * @offset  where to start reading from (see below).
0013  * @buf     pointer to a "void *" buffer for reading into (if
0014  *      *@buf is NULL, a buffer will be allocated, and
0015  *      @buf_size will be ignored)
0016  * @buf_size    size of buf, if already allocated. If @buf not
0017  *      allocated, this is the largest size to allocate.
0018  * @file_size   if non-NULL, the full size of @file will be
0019  *      written here.
0020  * @id      the kernel_read_file_id identifying the type of
0021  *      file contents being read (for LSMs to examine)
0022  *
0023  * @offset must be 0 unless both @buf and @file_size are non-NULL
0024  * (i.e. the caller must be expecting to read partial file contents
0025  * via an already-allocated @buf, in at most @buf_size chunks, and
0026  * will be able to determine when the entire file was read by
0027  * checking @file_size). This isn't a recommended way to read a
0028  * file, though, since it is possible that the contents might
0029  * change between calls to kernel_read_file().
0030  *
0031  * Returns number of bytes read (no single read will be bigger
0032  * than SSIZE_MAX), or negative on error.
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     /* The file is too big for sane activities. */
0061     if (i_size > SSIZE_MAX) {
0062         ret = -EFBIG;
0063         goto out;
0064     }
0065     /* The entire file cannot be read in one buffer. */
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);