diff options
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 198 |
1 files changed, 159 insertions, 39 deletions
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/pid_namespace.h> | 42 | #include <linux/pid_namespace.h> |
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/namei.h> | 44 | #include <linux/namei.h> |
45 | #include <linux/proc_fs.h> | ||
46 | #include <linux/mount.h> | 45 | #include <linux/mount.h> |
47 | #include <linux/security.h> | 46 | #include <linux/security.h> |
48 | #include <linux/syscalls.h> | 47 | #include <linux/syscalls.h> |
@@ -55,6 +54,7 @@ | |||
55 | #include <linux/fs_struct.h> | 54 | #include <linux/fs_struct.h> |
56 | #include <linux/pipe_fs_i.h> | 55 | #include <linux/pipe_fs_i.h> |
57 | #include <linux/oom.h> | 56 | #include <linux/oom.h> |
57 | #include <linux/compat.h> | ||
58 | 58 | ||
59 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
60 | #include <asm/mmu_context.h> | 60 | #include <asm/mmu_context.h> |
@@ -115,13 +115,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
115 | struct file *file; | 115 | struct file *file; |
116 | char *tmp = getname(library); | 116 | char *tmp = getname(library); |
117 | int error = PTR_ERR(tmp); | 117 | int error = PTR_ERR(tmp); |
118 | static const struct open_flags uselib_flags = { | ||
119 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
120 | .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, | ||
121 | .intent = LOOKUP_OPEN | ||
122 | }; | ||
118 | 123 | ||
119 | if (IS_ERR(tmp)) | 124 | if (IS_ERR(tmp)) |
120 | goto out; | 125 | goto out; |
121 | 126 | ||
122 | file = do_filp_open(AT_FDCWD, tmp, | 127 | file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); |
123 | O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, | ||
124 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
125 | putname(tmp); | 128 | putname(tmp); |
126 | error = PTR_ERR(file); | 129 | error = PTR_ERR(file); |
127 | if (IS_ERR(file)) | 130 | if (IS_ERR(file)) |
@@ -163,8 +166,13 @@ out: | |||
163 | } | 166 | } |
164 | 167 | ||
165 | #ifdef CONFIG_MMU | 168 | #ifdef CONFIG_MMU |
166 | 169 | /* | |
167 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | 170 | * The nascent bprm->mm is not visible until exec_mmap() but it can |
171 | * use a lot of memory, account these pages in current->mm temporary | ||
172 | * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we | ||
173 | * change the counter back via acct_arg_size(0). | ||
174 | */ | ||
175 | static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | ||
168 | { | 176 | { |
169 | struct mm_struct *mm = current->mm; | 177 | struct mm_struct *mm = current->mm; |
170 | long diff = (long)(pages - bprm->vma_pages); | 178 | long diff = (long)(pages - bprm->vma_pages); |
@@ -183,7 +191,7 @@ void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | |||
183 | #endif | 191 | #endif |
184 | } | 192 | } |
185 | 193 | ||
186 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 194 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, |
187 | int write) | 195 | int write) |
188 | { | 196 | { |
189 | struct page *page; | 197 | struct page *page; |
@@ -191,7 +199,7 @@ struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
191 | 199 | ||
192 | #ifdef CONFIG_STACK_GROWSUP | 200 | #ifdef CONFIG_STACK_GROWSUP |
193 | if (write) { | 201 | if (write) { |
194 | ret = expand_stack_downwards(bprm->vma, pos); | 202 | ret = expand_downwards(bprm->vma, pos); |
195 | if (ret < 0) | 203 | if (ret < 0) |
196 | return NULL; | 204 | return NULL; |
197 | } | 205 | } |
@@ -302,11 +310,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
302 | 310 | ||
303 | #else | 311 | #else |
304 | 312 | ||
305 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | 313 | static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
306 | { | 314 | { |
307 | } | 315 | } |
308 | 316 | ||
309 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 317 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, |
310 | int write) | 318 | int write) |
311 | { | 319 | { |
312 | struct page *page; | 320 | struct page *page; |
@@ -395,22 +403,56 @@ err: | |||
395 | return err; | 403 | return err; |
396 | } | 404 | } |
397 | 405 | ||
406 | struct user_arg_ptr { | ||
407 | #ifdef CONFIG_COMPAT | ||
408 | bool is_compat; | ||
409 | #endif | ||
410 | union { | ||
411 | const char __user *const __user *native; | ||
412 | #ifdef CONFIG_COMPAT | ||
413 | compat_uptr_t __user *compat; | ||
414 | #endif | ||
415 | } ptr; | ||
416 | }; | ||
417 | |||
418 | static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) | ||
419 | { | ||
420 | const char __user *native; | ||
421 | |||
422 | #ifdef CONFIG_COMPAT | ||
423 | if (unlikely(argv.is_compat)) { | ||
424 | compat_uptr_t compat; | ||
425 | |||
426 | if (get_user(compat, argv.ptr.compat + nr)) | ||
427 | return ERR_PTR(-EFAULT); | ||
428 | |||
429 | return compat_ptr(compat); | ||
430 | } | ||
431 | #endif | ||
432 | |||
433 | if (get_user(native, argv.ptr.native + nr)) | ||
434 | return ERR_PTR(-EFAULT); | ||
435 | |||
436 | return native; | ||
437 | } | ||
438 | |||
398 | /* | 439 | /* |
399 | * count() counts the number of strings in array ARGV. | 440 | * count() counts the number of strings in array ARGV. |
400 | */ | 441 | */ |
401 | static int count(const char __user * const __user * argv, int max) | 442 | static int count(struct user_arg_ptr argv, int max) |
402 | { | 443 | { |
403 | int i = 0; | 444 | int i = 0; |
404 | 445 | ||
405 | if (argv != NULL) { | 446 | if (argv.ptr.native != NULL) { |
406 | for (;;) { | 447 | for (;;) { |
407 | const char __user * p; | 448 | const char __user *p = get_user_arg_ptr(argv, i); |
408 | 449 | ||
409 | if (get_user(p, argv)) | ||
410 | return -EFAULT; | ||
411 | if (!p) | 450 | if (!p) |
412 | break; | 451 | break; |
413 | argv++; | 452 | |
453 | if (IS_ERR(p)) | ||
454 | return -EFAULT; | ||
455 | |||
414 | if (i++ >= max) | 456 | if (i++ >= max) |
415 | return -E2BIG; | 457 | return -E2BIG; |
416 | 458 | ||
@@ -427,7 +469,7 @@ static int count(const char __user * const __user * argv, int max) | |||
427 | * processes's memory to the new process's stack. The call to get_user_pages() | 469 | * processes's memory to the new process's stack. The call to get_user_pages() |
428 | * ensures the destination page is created and not swapped out. | 470 | * ensures the destination page is created and not swapped out. |
429 | */ | 471 | */ |
430 | static int copy_strings(int argc, const char __user *const __user *argv, | 472 | static int copy_strings(int argc, struct user_arg_ptr argv, |
431 | struct linux_binprm *bprm) | 473 | struct linux_binprm *bprm) |
432 | { | 474 | { |
433 | struct page *kmapped_page = NULL; | 475 | struct page *kmapped_page = NULL; |
@@ -440,16 +482,18 @@ static int copy_strings(int argc, const char __user *const __user *argv, | |||
440 | int len; | 482 | int len; |
441 | unsigned long pos; | 483 | unsigned long pos; |
442 | 484 | ||
443 | if (get_user(str, argv+argc) || | 485 | ret = -EFAULT; |
444 | !(len = strnlen_user(str, MAX_ARG_STRLEN))) { | 486 | str = get_user_arg_ptr(argv, argc); |
445 | ret = -EFAULT; | 487 | if (IS_ERR(str)) |
446 | goto out; | 488 | goto out; |
447 | } | ||
448 | 489 | ||
449 | if (!valid_arg_len(bprm, len)) { | 490 | len = strnlen_user(str, MAX_ARG_STRLEN); |
450 | ret = -E2BIG; | 491 | if (!len) |
492 | goto out; | ||
493 | |||
494 | ret = -E2BIG; | ||
495 | if (!valid_arg_len(bprm, len)) | ||
451 | goto out; | 496 | goto out; |
452 | } | ||
453 | 497 | ||
454 | /* We're going to work our way backwords. */ | 498 | /* We're going to work our way backwords. */ |
455 | pos = bprm->p; | 499 | pos = bprm->p; |
@@ -516,14 +560,19 @@ out: | |||
516 | /* | 560 | /* |
517 | * Like copy_strings, but get argv and its values from kernel memory. | 561 | * Like copy_strings, but get argv and its values from kernel memory. |
518 | */ | 562 | */ |
519 | int copy_strings_kernel(int argc, const char *const *argv, | 563 | int copy_strings_kernel(int argc, const char *const *__argv, |
520 | struct linux_binprm *bprm) | 564 | struct linux_binprm *bprm) |
521 | { | 565 | { |
522 | int r; | 566 | int r; |
523 | mm_segment_t oldfs = get_fs(); | 567 | mm_segment_t oldfs = get_fs(); |
568 | struct user_arg_ptr argv = { | ||
569 | .ptr.native = (const char __user *const __user *)__argv, | ||
570 | }; | ||
571 | |||
524 | set_fs(KERNEL_DS); | 572 | set_fs(KERNEL_DS); |
525 | r = copy_strings(argc, (const char __user *const __user *)argv, bprm); | 573 | r = copy_strings(argc, argv, bprm); |
526 | set_fs(oldfs); | 574 | set_fs(oldfs); |
575 | |||
527 | return r; | 576 | return r; |
528 | } | 577 | } |
529 | EXPORT_SYMBOL(copy_strings_kernel); | 578 | EXPORT_SYMBOL(copy_strings_kernel); |
@@ -550,7 +599,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
550 | unsigned long length = old_end - old_start; | 599 | unsigned long length = old_end - old_start; |
551 | unsigned long new_start = old_start - shift; | 600 | unsigned long new_start = old_start - shift; |
552 | unsigned long new_end = old_end - shift; | 601 | unsigned long new_end = old_end - shift; |
553 | struct mmu_gather *tlb; | 602 | struct mmu_gather tlb; |
554 | 603 | ||
555 | BUG_ON(new_start > new_end); | 604 | BUG_ON(new_start > new_end); |
556 | 605 | ||
@@ -576,12 +625,12 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
576 | return -ENOMEM; | 625 | return -ENOMEM; |
577 | 626 | ||
578 | lru_add_drain(); | 627 | lru_add_drain(); |
579 | tlb = tlb_gather_mmu(mm, 0); | 628 | tlb_gather_mmu(&tlb, mm, 0); |
580 | if (new_end > old_start) { | 629 | if (new_end > old_start) { |
581 | /* | 630 | /* |
582 | * when the old and new regions overlap clear from new_end. | 631 | * when the old and new regions overlap clear from new_end. |
583 | */ | 632 | */ |
584 | free_pgd_range(tlb, new_end, old_end, new_end, | 633 | free_pgd_range(&tlb, new_end, old_end, new_end, |
585 | vma->vm_next ? vma->vm_next->vm_start : 0); | 634 | vma->vm_next ? vma->vm_next->vm_start : 0); |
586 | } else { | 635 | } else { |
587 | /* | 636 | /* |
@@ -590,10 +639,10 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
590 | * have constraints on va-space that make this illegal (IA64) - | 639 | * have constraints on va-space that make this illegal (IA64) - |
591 | * for the others its just a little faster. | 640 | * for the others its just a little faster. |
592 | */ | 641 | */ |
593 | free_pgd_range(tlb, old_start, old_end, new_end, | 642 | free_pgd_range(&tlb, old_start, old_end, new_end, |
594 | vma->vm_next ? vma->vm_next->vm_start : 0); | 643 | vma->vm_next ? vma->vm_next->vm_start : 0); |
595 | } | 644 | } |
596 | tlb_finish_mmu(tlb, new_end, old_end); | 645 | tlb_finish_mmu(&tlb, new_end, old_end); |
597 | 646 | ||
598 | /* | 647 | /* |
599 | * Shrink the vma to just the new range. Always succeeds. | 648 | * Shrink the vma to just the new range. Always succeeds. |
@@ -721,10 +770,13 @@ struct file *open_exec(const char *name) | |||
721 | { | 770 | { |
722 | struct file *file; | 771 | struct file *file; |
723 | int err; | 772 | int err; |
773 | static const struct open_flags open_exec_flags = { | ||
774 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
775 | .acc_mode = MAY_EXEC | MAY_OPEN, | ||
776 | .intent = LOOKUP_OPEN | ||
777 | }; | ||
724 | 778 | ||
725 | file = do_filp_open(AT_FDCWD, name, | 779 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); |
726 | O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0, | ||
727 | MAY_EXEC | MAY_OPEN); | ||
728 | if (IS_ERR(file)) | 780 | if (IS_ERR(file)) |
729 | goto out; | 781 | goto out; |
730 | 782 | ||
@@ -998,6 +1050,7 @@ char *get_task_comm(char *buf, struct task_struct *tsk) | |||
998 | task_unlock(tsk); | 1050 | task_unlock(tsk); |
999 | return buf; | 1051 | return buf; |
1000 | } | 1052 | } |
1053 | EXPORT_SYMBOL_GPL(get_task_comm); | ||
1001 | 1054 | ||
1002 | void set_task_comm(struct task_struct *tsk, char *buf) | 1055 | void set_task_comm(struct task_struct *tsk, char *buf) |
1003 | { | 1056 | { |
@@ -1373,10 +1426,10 @@ EXPORT_SYMBOL(search_binary_handler); | |||
1373 | /* | 1426 | /* |
1374 | * sys_execve() executes a new program. | 1427 | * sys_execve() executes a new program. |
1375 | */ | 1428 | */ |
1376 | int do_execve(const char * filename, | 1429 | static int do_execve_common(const char *filename, |
1377 | const char __user *const __user *argv, | 1430 | struct user_arg_ptr argv, |
1378 | const char __user *const __user *envp, | 1431 | struct user_arg_ptr envp, |
1379 | struct pt_regs * regs) | 1432 | struct pt_regs *regs) |
1380 | { | 1433 | { |
1381 | struct linux_binprm *bprm; | 1434 | struct linux_binprm *bprm; |
1382 | struct file *file; | 1435 | struct file *file; |
@@ -1483,6 +1536,34 @@ out_ret: | |||
1483 | return retval; | 1536 | return retval; |
1484 | } | 1537 | } |
1485 | 1538 | ||
1539 | int do_execve(const char *filename, | ||
1540 | const char __user *const __user *__argv, | ||
1541 | const char __user *const __user *__envp, | ||
1542 | struct pt_regs *regs) | ||
1543 | { | ||
1544 | struct user_arg_ptr argv = { .ptr.native = __argv }; | ||
1545 | struct user_arg_ptr envp = { .ptr.native = __envp }; | ||
1546 | return do_execve_common(filename, argv, envp, regs); | ||
1547 | } | ||
1548 | |||
1549 | #ifdef CONFIG_COMPAT | ||
1550 | int compat_do_execve(char *filename, | ||
1551 | compat_uptr_t __user *__argv, | ||
1552 | compat_uptr_t __user *__envp, | ||
1553 | struct pt_regs *regs) | ||
1554 | { | ||
1555 | struct user_arg_ptr argv = { | ||
1556 | .is_compat = true, | ||
1557 | .ptr.compat = __argv, | ||
1558 | }; | ||
1559 | struct user_arg_ptr envp = { | ||
1560 | .is_compat = true, | ||
1561 | .ptr.compat = __envp, | ||
1562 | }; | ||
1563 | return do_execve_common(filename, argv, envp, regs); | ||
1564 | } | ||
1565 | #endif | ||
1566 | |||
1486 | void set_binfmt(struct linux_binfmt *new) | 1567 | void set_binfmt(struct linux_binfmt *new) |
1487 | { | 1568 | { |
1488 | struct mm_struct *mm = current->mm; | 1569 | struct mm_struct *mm = current->mm; |
@@ -1542,6 +1623,41 @@ expand_fail: | |||
1542 | return ret; | 1623 | return ret; |
1543 | } | 1624 | } |
1544 | 1625 | ||
1626 | static int cn_print_exe_file(struct core_name *cn) | ||
1627 | { | ||
1628 | struct file *exe_file; | ||
1629 | char *pathbuf, *path, *p; | ||
1630 | int ret; | ||
1631 | |||
1632 | exe_file = get_mm_exe_file(current->mm); | ||
1633 | if (!exe_file) | ||
1634 | return cn_printf(cn, "(unknown)"); | ||
1635 | |||
1636 | pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY); | ||
1637 | if (!pathbuf) { | ||
1638 | ret = -ENOMEM; | ||
1639 | goto put_exe_file; | ||
1640 | } | ||
1641 | |||
1642 | path = d_path(&exe_file->f_path, pathbuf, PATH_MAX); | ||
1643 | if (IS_ERR(path)) { | ||
1644 | ret = PTR_ERR(path); | ||
1645 | goto free_buf; | ||
1646 | } | ||
1647 | |||
1648 | for (p = path; *p; p++) | ||
1649 | if (*p == '/') | ||
1650 | *p = '!'; | ||
1651 | |||
1652 | ret = cn_printf(cn, "%s", path); | ||
1653 | |||
1654 | free_buf: | ||
1655 | kfree(pathbuf); | ||
1656 | put_exe_file: | ||
1657 | fput(exe_file); | ||
1658 | return ret; | ||
1659 | } | ||
1660 | |||
1545 | /* format_corename will inspect the pattern parameter, and output a | 1661 | /* format_corename will inspect the pattern parameter, and output a |
1546 | * name into corename, which must have space for at least | 1662 | * name into corename, which must have space for at least |
1547 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1663 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
@@ -1613,6 +1729,9 @@ static int format_corename(struct core_name *cn, long signr) | |||
1613 | case 'e': | 1729 | case 'e': |
1614 | err = cn_printf(cn, "%s", current->comm); | 1730 | err = cn_printf(cn, "%s", current->comm); |
1615 | break; | 1731 | break; |
1732 | case 'E': | ||
1733 | err = cn_print_exe_file(cn); | ||
1734 | break; | ||
1616 | /* core limit size */ | 1735 | /* core limit size */ |
1617 | case 'c': | 1736 | case 'c': |
1618 | err = cn_printf(cn, "%lu", | 1737 | err = cn_printf(cn, "%lu", |
@@ -1653,6 +1772,7 @@ static int zap_process(struct task_struct *start, int exit_code) | |||
1653 | 1772 | ||
1654 | t = start; | 1773 | t = start; |
1655 | do { | 1774 | do { |
1775 | task_clear_group_stop_pending(t); | ||
1656 | if (t != current && t->mm) { | 1776 | if (t != current && t->mm) { |
1657 | sigaddset(&t->pending.signal, SIGKILL); | 1777 | sigaddset(&t->pending.signal, SIGKILL); |
1658 | signal_wake_up(t, 1); | 1778 | signal_wake_up(t, 1); |
@@ -1869,7 +1989,7 @@ static void wait_for_dump_helpers(struct file *file) | |||
1869 | 1989 | ||
1870 | 1990 | ||
1871 | /* | 1991 | /* |
1872 | * uhm_pipe_setup | 1992 | * umh_pipe_setup |
1873 | * helper function to customize the process used | 1993 | * helper function to customize the process used |
1874 | * to collect the core in userspace. Specifically | 1994 | * to collect the core in userspace. Specifically |
1875 | * it sets up a pipe and installs it as fd 0 (stdin) | 1995 | * it sets up a pipe and installs it as fd 0 (stdin) |