aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c100
1 files changed, 98 insertions, 2 deletions
diff --git a/fs/exec.c b/fs/exec.c
index dcd4ac7d3f1e..c4010b8207a1 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>
@@ -198,8 +199,12 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
198 return NULL; 199 return NULL;
199 } 200 }
200#endif 201#endif
201 ret = get_user_pages(current, bprm->mm, pos, 202 /*
202 1, write, 1, &page, NULL); 203 * We are doing an exec(). 'current' is the process
204 * doing the exec and bprm->mm is the new process's mm.
205 */
206 ret = get_user_pages_remote(current, bprm->mm, pos, 1, write,
207 1, &page, NULL);
203 if (ret <= 0) 208 if (ret <= 0)
204 return NULL; 209 return NULL;
205 210
@@ -831,6 +836,97 @@ int kernel_read(struct file *file, loff_t offset,
831 836
832EXPORT_SYMBOL(kernel_read); 837EXPORT_SYMBOL(kernel_read);
833 838
839int kernel_read_file(struct file *file, void **buf, loff_t *size,
840 loff_t max_size, enum kernel_read_file_id id)
841{
842 loff_t i_size, pos;
843 ssize_t bytes = 0;
844 int ret;
845
846 if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
847 return -EINVAL;
848
849 ret = security_kernel_read_file(file, id);
850 if (ret)
851 return ret;
852
853 i_size = i_size_read(file_inode(file));
854 if (max_size > 0 && i_size > max_size)
855 return -EFBIG;
856 if (i_size <= 0)
857 return -EINVAL;
858
859 *buf = vmalloc(i_size);
860 if (!*buf)
861 return -ENOMEM;
862
863 pos = 0;
864 while (pos < i_size) {
865 bytes = kernel_read(file, pos, (char *)(*buf) + pos,
866 i_size - pos);
867 if (bytes < 0) {
868 ret = bytes;
869 goto out;
870 }
871
872 if (bytes == 0)
873 break;
874 pos += bytes;
875 }
876
877 if (pos != i_size) {
878 ret = -EIO;
879 goto out;
880 }
881
882 ret = security_kernel_post_read_file(file, *buf, i_size, id);
883 if (!ret)
884 *size = pos;
885
886out:
887 if (ret < 0) {
888 vfree(*buf);
889 *buf = NULL;
890 }
891 return ret;
892}
893EXPORT_SYMBOL_GPL(kernel_read_file);
894
895int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
896 loff_t max_size, enum kernel_read_file_id id)
897{
898 struct file *file;
899 int ret;
900
901 if (!path || !*path)
902 return -EINVAL;
903
904 file = filp_open(path, O_RDONLY, 0);
905 if (IS_ERR(file))
906 return PTR_ERR(file);
907
908 ret = kernel_read_file(file, buf, size, max_size, id);
909 fput(file);
910 return ret;
911}
912EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
913
914int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
915 enum kernel_read_file_id id)
916{
917 struct fd f = fdget(fd);
918 int ret = -EBADF;
919
920 if (!f.file)
921 goto out;
922
923 ret = kernel_read_file(f.file, buf, size, max_size, id);
924out:
925 fdput(f);
926 return ret;
927}
928EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
929
834ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) 930ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
835{ 931{
836 ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); 932 ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);