aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/fs/exec.c b/fs/exec.c
index dcd4ac7d3f1e..9bdf0edf570d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -56,6 +56,7 @@
56#include <linux/pipe_fs_i.h> 56#include <linux/pipe_fs_i.h>
57#include <linux/oom.h> 57#include <linux/oom.h>
58#include <linux/compat.h> 58#include <linux/compat.h>
59#include <linux/vmalloc.h>
59 60
60#include <asm/uaccess.h> 61#include <asm/uaccess.h>
61#include <asm/mmu_context.h> 62#include <asm/mmu_context.h>
@@ -831,6 +832,97 @@ int kernel_read(struct file *file, loff_t offset,
831 832
832EXPORT_SYMBOL(kernel_read); 833EXPORT_SYMBOL(kernel_read);
833 834
835int kernel_read_file(struct file *file, void **buf, loff_t *size,
836 loff_t max_size, enum kernel_read_file_id id)
837{
838 loff_t i_size, pos;
839 ssize_t bytes = 0;
840 int ret;
841
842 if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
843 return -EINVAL;
844
845 ret = security_kernel_read_file(file, id);
846 if (ret)
847 return ret;
848
849 i_size = i_size_read(file_inode(file));
850 if (max_size > 0 && i_size > max_size)
851 return -EFBIG;
852 if (i_size <= 0)
853 return -EINVAL;
854
855 *buf = vmalloc(i_size);
856 if (!*buf)
857 return -ENOMEM;
858
859 pos = 0;
860 while (pos < i_size) {
861 bytes = kernel_read(file, pos, (char *)(*buf) + pos,
862 i_size - pos);
863 if (bytes < 0) {
864 ret = bytes;
865 goto out;
866 }
867
868 if (bytes == 0)
869 break;
870 pos += bytes;
871 }
872
873 if (pos != i_size) {
874 ret = -EIO;
875 goto out;
876 }
877
878 ret = security_kernel_post_read_file(file, *buf, i_size, id);
879 if (!ret)
880 *size = pos;
881
882out:
883 if (ret < 0) {
884 vfree(*buf);
885 *buf = NULL;
886 }
887 return ret;
888}
889EXPORT_SYMBOL_GPL(kernel_read_file);
890
891int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
892 loff_t max_size, enum kernel_read_file_id id)
893{
894 struct file *file;
895 int ret;
896
897 if (!path || !*path)
898 return -EINVAL;
899
900 file = filp_open(path, O_RDONLY, 0);
901 if (IS_ERR(file))
902 return PTR_ERR(file);
903
904 ret = kernel_read_file(file, buf, size, max_size, id);
905 fput(file);
906 return ret;
907}
908EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
909
910int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
911 enum kernel_read_file_id id)
912{
913 struct fd f = fdget(fd);
914 int ret = -EBADF;
915
916 if (!f.file)
917 goto out;
918
919 ret = kernel_read_file(f.file, buf, size, max_size, id);
920out:
921 fdput(f);
922 return ret;
923}
924EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
925
834ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) 926ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
835{ 927{
836 ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); 928 ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);