aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 526a0399d963..89d788ca7829 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -55,6 +55,7 @@
55#include <linux/fs_struct.h> 55#include <linux/fs_struct.h>
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 59
59#include <asm/uaccess.h> 60#include <asm/uaccess.h>
60#include <asm/mmu_context.h> 61#include <asm/mmu_context.h>
@@ -167,7 +168,7 @@ out:
167 168
168#ifdef CONFIG_MMU 169#ifdef CONFIG_MMU
169 170
170void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) 171static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
171{ 172{
172 struct mm_struct *mm = current->mm; 173 struct mm_struct *mm = current->mm;
173 long diff = (long)(pages - bprm->vma_pages); 174 long diff = (long)(pages - bprm->vma_pages);
@@ -186,7 +187,7 @@ void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
186#endif 187#endif
187} 188}
188 189
189struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, 190static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
190 int write) 191 int write)
191{ 192{
192 struct page *page; 193 struct page *page;
@@ -305,11 +306,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len)
305 306
306#else 307#else
307 308
308void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) 309static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
309{ 310{
310} 311}
311 312
312struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, 313static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
313 int write) 314 int write)
314{ 315{
315 struct page *page; 316 struct page *page;
@@ -399,17 +400,36 @@ err:
399} 400}
400 401
401struct user_arg_ptr { 402struct user_arg_ptr {
402 const char __user *const __user *native; 403#ifdef CONFIG_COMPAT
404 bool is_compat;
405#endif
406 union {
407 const char __user *const __user *native;
408#ifdef CONFIG_COMPAT
409 compat_uptr_t __user *compat;
410#endif
411 } ptr;
403}; 412};
404 413
405static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) 414static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
406{ 415{
407 const char __user *ptr; 416 const char __user *native;
417
418#ifdef CONFIG_COMPAT
419 if (unlikely(argv.is_compat)) {
420 compat_uptr_t compat;
421
422 if (get_user(compat, argv.ptr.compat + nr))
423 return ERR_PTR(-EFAULT);
408 424
409 if (get_user(ptr, argv.native + nr)) 425 return compat_ptr(compat);
426 }
427#endif
428
429 if (get_user(native, argv.ptr.native + nr))
410 return ERR_PTR(-EFAULT); 430 return ERR_PTR(-EFAULT);
411 431
412 return ptr; 432 return native;
413} 433}
414 434
415/* 435/*
@@ -419,7 +439,7 @@ static int count(struct user_arg_ptr argv, int max)
419{ 439{
420 int i = 0; 440 int i = 0;
421 441
422 if (argv.native != NULL) { 442 if (argv.ptr.native != NULL) {
423 for (;;) { 443 for (;;) {
424 const char __user *p = get_user_arg_ptr(argv, i); 444 const char __user *p = get_user_arg_ptr(argv, i);
425 445
@@ -542,7 +562,7 @@ int copy_strings_kernel(int argc, const char *const *__argv,
542 int r; 562 int r;
543 mm_segment_t oldfs = get_fs(); 563 mm_segment_t oldfs = get_fs();
544 struct user_arg_ptr argv = { 564 struct user_arg_ptr argv = {
545 .native = (const char __user *const __user *)__argv, 565 .ptr.native = (const char __user *const __user *)__argv,
546 }; 566 };
547 567
548 set_fs(KERNEL_DS); 568 set_fs(KERNEL_DS);
@@ -1516,10 +1536,28 @@ int do_execve(const char *filename,
1516 const char __user *const __user *__envp, 1536 const char __user *const __user *__envp,
1517 struct pt_regs *regs) 1537 struct pt_regs *regs)
1518{ 1538{
1519 struct user_arg_ptr argv = { .native = __argv }; 1539 struct user_arg_ptr argv = { .ptr.native = __argv };
1520 struct user_arg_ptr envp = { .native = __envp }; 1540 struct user_arg_ptr envp = { .ptr.native = __envp };
1541 return do_execve_common(filename, argv, envp, regs);
1542}
1543
1544#ifdef CONFIG_COMPAT
1545int compat_do_execve(char *filename,
1546 compat_uptr_t __user *__argv,
1547 compat_uptr_t __user *__envp,
1548 struct pt_regs *regs)
1549{
1550 struct user_arg_ptr argv = {
1551 .is_compat = true,
1552 .ptr.compat = __argv,
1553 };
1554 struct user_arg_ptr envp = {
1555 .is_compat = true,
1556 .ptr.compat = __envp,
1557 };
1521 return do_execve_common(filename, argv, envp, regs); 1558 return do_execve_common(filename, argv, envp, regs);
1522} 1559}
1560#endif
1523 1561
1524void set_binfmt(struct linux_binfmt *new) 1562void set_binfmt(struct linux_binfmt *new)
1525{ 1563{