diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2011-08-27 09:43:54 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2011-08-27 10:06:11 -0400 |
commit | 7b1bb388bc879ffcc6c69b567816d5c354afe42b (patch) | |
tree | 5a217fdfb0b5e5a327bdcd624506337c1ae1fe32 /fs/exec.c | |
parent | 7d754596756240fa918b94cd0c3011c77a638987 (diff) | |
parent | 02f8c6aee8df3cdc935e9bdd4f2d020306035dbe (diff) |
Merge 'Linux v3.0' into Litmus
Some notes:
* Litmus^RT scheduling class is the topmost scheduling class
(above stop_sched_class).
* scheduler_ipi() function (e.g., in smp_reschedule_interrupt())
may increase IPI latencies.
* Added path into schedule() to quickly re-evaluate scheduling
decision without becoming preemptive again. This used to be
a standard path before the removal of BKL.
Conflicts:
Makefile
arch/arm/kernel/calls.S
arch/arm/kernel/smp.c
arch/x86/include/asm/unistd_32.h
arch/x86/kernel/smp.c
arch/x86/kernel/syscall_table_32.S
include/linux/hrtimer.h
kernel/printk.c
kernel/sched.c
kernel/sched_fair.c
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 405 |
1 files changed, 297 insertions, 108 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> |
@@ -54,6 +53,8 @@ | |||
54 | #include <linux/fsnotify.h> | 53 | #include <linux/fsnotify.h> |
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> |
56 | #include <linux/oom.h> | ||
57 | #include <linux/compat.h> | ||
57 | 58 | ||
58 | #include <litmus/litmus.h> | 59 | #include <litmus/litmus.h> |
59 | 60 | ||
@@ -67,6 +68,12 @@ char core_pattern[CORENAME_MAX_SIZE] = "core"; | |||
67 | unsigned int core_pipe_limit; | 68 | unsigned int core_pipe_limit; |
68 | int suid_dumpable = 0; | 69 | int suid_dumpable = 0; |
69 | 70 | ||
71 | struct core_name { | ||
72 | char *corename; | ||
73 | int used, size; | ||
74 | }; | ||
75 | static atomic_t call_count = ATOMIC_INIT(1); | ||
76 | |||
70 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 77 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
71 | 78 | ||
72 | static LIST_HEAD(formats); | 79 | static LIST_HEAD(formats); |
@@ -110,13 +117,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
110 | struct file *file; | 117 | struct file *file; |
111 | char *tmp = getname(library); | 118 | char *tmp = getname(library); |
112 | int error = PTR_ERR(tmp); | 119 | int error = PTR_ERR(tmp); |
120 | static const struct open_flags uselib_flags = { | ||
121 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
122 | .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, | ||
123 | .intent = LOOKUP_OPEN | ||
124 | }; | ||
113 | 125 | ||
114 | if (IS_ERR(tmp)) | 126 | if (IS_ERR(tmp)) |
115 | goto out; | 127 | goto out; |
116 | 128 | ||
117 | file = do_filp_open(AT_FDCWD, tmp, | 129 | file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); |
118 | O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0, | ||
119 | MAY_READ | MAY_EXEC | MAY_OPEN); | ||
120 | putname(tmp); | 130 | putname(tmp); |
121 | error = PTR_ERR(file); | 131 | error = PTR_ERR(file); |
122 | if (IS_ERR(file)) | 132 | if (IS_ERR(file)) |
@@ -158,6 +168,30 @@ out: | |||
158 | } | 168 | } |
159 | 169 | ||
160 | #ifdef CONFIG_MMU | 170 | #ifdef CONFIG_MMU |
171 | /* | ||
172 | * The nascent bprm->mm is not visible until exec_mmap() but it can | ||
173 | * use a lot of memory, account these pages in current->mm temporary | ||
174 | * for oom_badness()->get_mm_rss(). Once exec succeeds or fails, we | ||
175 | * change the counter back via acct_arg_size(0). | ||
176 | */ | ||
177 | static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | ||
178 | { | ||
179 | struct mm_struct *mm = current->mm; | ||
180 | long diff = (long)(pages - bprm->vma_pages); | ||
181 | |||
182 | if (!mm || !diff) | ||
183 | return; | ||
184 | |||
185 | bprm->vma_pages = pages; | ||
186 | |||
187 | #ifdef SPLIT_RSS_COUNTING | ||
188 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
189 | #else | ||
190 | spin_lock(&mm->page_table_lock); | ||
191 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
192 | spin_unlock(&mm->page_table_lock); | ||
193 | #endif | ||
194 | } | ||
161 | 195 | ||
162 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 196 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, |
163 | int write) | 197 | int write) |
@@ -167,7 +201,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
167 | 201 | ||
168 | #ifdef CONFIG_STACK_GROWSUP | 202 | #ifdef CONFIG_STACK_GROWSUP |
169 | if (write) { | 203 | if (write) { |
170 | ret = expand_stack_downwards(bprm->vma, pos); | 204 | ret = expand_downwards(bprm->vma, pos); |
171 | if (ret < 0) | 205 | if (ret < 0) |
172 | return NULL; | 206 | return NULL; |
173 | } | 207 | } |
@@ -181,6 +215,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
181 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; | 215 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; |
182 | struct rlimit *rlim; | 216 | struct rlimit *rlim; |
183 | 217 | ||
218 | acct_arg_size(bprm, size / PAGE_SIZE); | ||
219 | |||
184 | /* | 220 | /* |
185 | * We've historically supported up to 32 pages (ARG_MAX) | 221 | * We've historically supported up to 32 pages (ARG_MAX) |
186 | * of argument strings even with small stacks | 222 | * of argument strings even with small stacks |
@@ -249,6 +285,11 @@ static int __bprm_mm_init(struct linux_binprm *bprm) | |||
249 | vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; | 285 | vma->vm_flags = VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP; |
250 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); | 286 | vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
251 | INIT_LIST_HEAD(&vma->anon_vma_chain); | 287 | INIT_LIST_HEAD(&vma->anon_vma_chain); |
288 | |||
289 | err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); | ||
290 | if (err) | ||
291 | goto err; | ||
292 | |||
252 | err = insert_vm_struct(mm, vma); | 293 | err = insert_vm_struct(mm, vma); |
253 | if (err) | 294 | if (err) |
254 | goto err; | 295 | goto err; |
@@ -271,6 +312,10 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
271 | 312 | ||
272 | #else | 313 | #else |
273 | 314 | ||
315 | static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) | ||
316 | { | ||
317 | } | ||
318 | |||
274 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 319 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, |
275 | int write) | 320 | int write) |
276 | { | 321 | { |
@@ -360,22 +405,56 @@ err: | |||
360 | return err; | 405 | return err; |
361 | } | 406 | } |
362 | 407 | ||
408 | struct user_arg_ptr { | ||
409 | #ifdef CONFIG_COMPAT | ||
410 | bool is_compat; | ||
411 | #endif | ||
412 | union { | ||
413 | const char __user *const __user *native; | ||
414 | #ifdef CONFIG_COMPAT | ||
415 | compat_uptr_t __user *compat; | ||
416 | #endif | ||
417 | } ptr; | ||
418 | }; | ||
419 | |||
420 | static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr) | ||
421 | { | ||
422 | const char __user *native; | ||
423 | |||
424 | #ifdef CONFIG_COMPAT | ||
425 | if (unlikely(argv.is_compat)) { | ||
426 | compat_uptr_t compat; | ||
427 | |||
428 | if (get_user(compat, argv.ptr.compat + nr)) | ||
429 | return ERR_PTR(-EFAULT); | ||
430 | |||
431 | return compat_ptr(compat); | ||
432 | } | ||
433 | #endif | ||
434 | |||
435 | if (get_user(native, argv.ptr.native + nr)) | ||
436 | return ERR_PTR(-EFAULT); | ||
437 | |||
438 | return native; | ||
439 | } | ||
440 | |||
363 | /* | 441 | /* |
364 | * count() counts the number of strings in array ARGV. | 442 | * count() counts the number of strings in array ARGV. |
365 | */ | 443 | */ |
366 | static int count(const char __user * const __user * argv, int max) | 444 | static int count(struct user_arg_ptr argv, int max) |
367 | { | 445 | { |
368 | int i = 0; | 446 | int i = 0; |
369 | 447 | ||
370 | if (argv != NULL) { | 448 | if (argv.ptr.native != NULL) { |
371 | for (;;) { | 449 | for (;;) { |
372 | const char __user * p; | 450 | const char __user *p = get_user_arg_ptr(argv, i); |
373 | 451 | ||
374 | if (get_user(p, argv)) | ||
375 | return -EFAULT; | ||
376 | if (!p) | 452 | if (!p) |
377 | break; | 453 | break; |
378 | argv++; | 454 | |
455 | if (IS_ERR(p)) | ||
456 | return -EFAULT; | ||
457 | |||
379 | if (i++ >= max) | 458 | if (i++ >= max) |
380 | return -E2BIG; | 459 | return -E2BIG; |
381 | 460 | ||
@@ -392,7 +471,7 @@ static int count(const char __user * const __user * argv, int max) | |||
392 | * processes's memory to the new process's stack. The call to get_user_pages() | 471 | * processes's memory to the new process's stack. The call to get_user_pages() |
393 | * ensures the destination page is created and not swapped out. | 472 | * ensures the destination page is created and not swapped out. |
394 | */ | 473 | */ |
395 | static int copy_strings(int argc, const char __user *const __user *argv, | 474 | static int copy_strings(int argc, struct user_arg_ptr argv, |
396 | struct linux_binprm *bprm) | 475 | struct linux_binprm *bprm) |
397 | { | 476 | { |
398 | struct page *kmapped_page = NULL; | 477 | struct page *kmapped_page = NULL; |
@@ -405,16 +484,18 @@ static int copy_strings(int argc, const char __user *const __user *argv, | |||
405 | int len; | 484 | int len; |
406 | unsigned long pos; | 485 | unsigned long pos; |
407 | 486 | ||
408 | if (get_user(str, argv+argc) || | 487 | ret = -EFAULT; |
409 | !(len = strnlen_user(str, MAX_ARG_STRLEN))) { | 488 | str = get_user_arg_ptr(argv, argc); |
410 | ret = -EFAULT; | 489 | if (IS_ERR(str)) |
411 | goto out; | 490 | goto out; |
412 | } | ||
413 | 491 | ||
414 | if (!valid_arg_len(bprm, len)) { | 492 | len = strnlen_user(str, MAX_ARG_STRLEN); |
415 | ret = -E2BIG; | 493 | if (!len) |
494 | goto out; | ||
495 | |||
496 | ret = -E2BIG; | ||
497 | if (!valid_arg_len(bprm, len)) | ||
416 | goto out; | 498 | goto out; |
417 | } | ||
418 | 499 | ||
419 | /* We're going to work our way backwords. */ | 500 | /* We're going to work our way backwords. */ |
420 | pos = bprm->p; | 501 | pos = bprm->p; |
@@ -481,14 +562,19 @@ out: | |||
481 | /* | 562 | /* |
482 | * Like copy_strings, but get argv and its values from kernel memory. | 563 | * Like copy_strings, but get argv and its values from kernel memory. |
483 | */ | 564 | */ |
484 | int copy_strings_kernel(int argc, const char *const *argv, | 565 | int copy_strings_kernel(int argc, const char *const *__argv, |
485 | struct linux_binprm *bprm) | 566 | struct linux_binprm *bprm) |
486 | { | 567 | { |
487 | int r; | 568 | int r; |
488 | mm_segment_t oldfs = get_fs(); | 569 | mm_segment_t oldfs = get_fs(); |
570 | struct user_arg_ptr argv = { | ||
571 | .ptr.native = (const char __user *const __user *)__argv, | ||
572 | }; | ||
573 | |||
489 | set_fs(KERNEL_DS); | 574 | set_fs(KERNEL_DS); |
490 | r = copy_strings(argc, (const char __user *const __user *)argv, bprm); | 575 | r = copy_strings(argc, argv, bprm); |
491 | set_fs(oldfs); | 576 | set_fs(oldfs); |
577 | |||
492 | return r; | 578 | return r; |
493 | } | 579 | } |
494 | EXPORT_SYMBOL(copy_strings_kernel); | 580 | EXPORT_SYMBOL(copy_strings_kernel); |
@@ -515,7 +601,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
515 | unsigned long length = old_end - old_start; | 601 | unsigned long length = old_end - old_start; |
516 | unsigned long new_start = old_start - shift; | 602 | unsigned long new_start = old_start - shift; |
517 | unsigned long new_end = old_end - shift; | 603 | unsigned long new_end = old_end - shift; |
518 | struct mmu_gather *tlb; | 604 | struct mmu_gather tlb; |
519 | 605 | ||
520 | BUG_ON(new_start > new_end); | 606 | BUG_ON(new_start > new_end); |
521 | 607 | ||
@@ -541,12 +627,12 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
541 | return -ENOMEM; | 627 | return -ENOMEM; |
542 | 628 | ||
543 | lru_add_drain(); | 629 | lru_add_drain(); |
544 | tlb = tlb_gather_mmu(mm, 0); | 630 | tlb_gather_mmu(&tlb, mm, 0); |
545 | if (new_end > old_start) { | 631 | if (new_end > old_start) { |
546 | /* | 632 | /* |
547 | * when the old and new regions overlap clear from new_end. | 633 | * when the old and new regions overlap clear from new_end. |
548 | */ | 634 | */ |
549 | free_pgd_range(tlb, new_end, old_end, new_end, | 635 | free_pgd_range(&tlb, new_end, old_end, new_end, |
550 | vma->vm_next ? vma->vm_next->vm_start : 0); | 636 | vma->vm_next ? vma->vm_next->vm_start : 0); |
551 | } else { | 637 | } else { |
552 | /* | 638 | /* |
@@ -555,10 +641,10 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) | |||
555 | * have constraints on va-space that make this illegal (IA64) - | 641 | * have constraints on va-space that make this illegal (IA64) - |
556 | * for the others its just a little faster. | 642 | * for the others its just a little faster. |
557 | */ | 643 | */ |
558 | free_pgd_range(tlb, old_start, old_end, new_end, | 644 | free_pgd_range(&tlb, old_start, old_end, new_end, |
559 | vma->vm_next ? vma->vm_next->vm_start : 0); | 645 | vma->vm_next ? vma->vm_next->vm_start : 0); |
560 | } | 646 | } |
561 | tlb_finish_mmu(tlb, new_end, old_end); | 647 | tlb_finish_mmu(&tlb, new_end, old_end); |
562 | 648 | ||
563 | /* | 649 | /* |
564 | * Shrink the vma to just the new range. Always succeeds. | 650 | * Shrink the vma to just the new range. Always succeeds. |
@@ -686,10 +772,13 @@ struct file *open_exec(const char *name) | |||
686 | { | 772 | { |
687 | struct file *file; | 773 | struct file *file; |
688 | int err; | 774 | int err; |
775 | static const struct open_flags open_exec_flags = { | ||
776 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | ||
777 | .acc_mode = MAY_EXEC | MAY_OPEN, | ||
778 | .intent = LOOKUP_OPEN | ||
779 | }; | ||
689 | 780 | ||
690 | file = do_filp_open(AT_FDCWD, name, | 781 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); |
691 | O_LARGEFILE | O_RDONLY | FMODE_EXEC, 0, | ||
692 | MAY_EXEC | MAY_OPEN); | ||
693 | if (IS_ERR(file)) | 782 | if (IS_ERR(file)) |
694 | goto out; | 783 | goto out; |
695 | 784 | ||
@@ -761,6 +850,10 @@ static int exec_mmap(struct mm_struct *mm) | |||
761 | tsk->mm = mm; | 850 | tsk->mm = mm; |
762 | tsk->active_mm = mm; | 851 | tsk->active_mm = mm; |
763 | activate_mm(active_mm, mm); | 852 | activate_mm(active_mm, mm); |
853 | if (old_mm && tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | ||
854 | atomic_dec(&old_mm->oom_disable_count); | ||
855 | atomic_inc(&tsk->mm->oom_disable_count); | ||
856 | } | ||
764 | task_unlock(tsk); | 857 | task_unlock(tsk); |
765 | arch_pick_mmap_layout(mm); | 858 | arch_pick_mmap_layout(mm); |
766 | if (old_mm) { | 859 | if (old_mm) { |
@@ -959,6 +1052,7 @@ char *get_task_comm(char *buf, struct task_struct *tsk) | |||
959 | task_unlock(tsk); | 1052 | task_unlock(tsk); |
960 | return buf; | 1053 | return buf; |
961 | } | 1054 | } |
1055 | EXPORT_SYMBOL_GPL(get_task_comm); | ||
962 | 1056 | ||
963 | void set_task_comm(struct task_struct *tsk, char *buf) | 1057 | void set_task_comm(struct task_struct *tsk, char *buf) |
964 | { | 1058 | { |
@@ -994,13 +1088,15 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
994 | /* | 1088 | /* |
995 | * Release all of the old mmap stuff | 1089 | * Release all of the old mmap stuff |
996 | */ | 1090 | */ |
1091 | acct_arg_size(bprm, 0); | ||
997 | retval = exec_mmap(bprm->mm); | 1092 | retval = exec_mmap(bprm->mm); |
998 | if (retval) | 1093 | if (retval) |
999 | goto out; | 1094 | goto out; |
1000 | 1095 | ||
1001 | bprm->mm = NULL; /* We're using it now */ | 1096 | bprm->mm = NULL; /* We're using it now */ |
1002 | 1097 | ||
1003 | current->flags &= ~PF_RANDOMIZE; | 1098 | set_fs(USER_DS); |
1099 | current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD); | ||
1004 | flush_thread(); | 1100 | flush_thread(); |
1005 | current->personality &= ~bprm->per_clear; | 1101 | current->personality &= ~bprm->per_clear; |
1006 | 1102 | ||
@@ -1080,14 +1176,14 @@ EXPORT_SYMBOL(setup_new_exec); | |||
1080 | */ | 1176 | */ |
1081 | int prepare_bprm_creds(struct linux_binprm *bprm) | 1177 | int prepare_bprm_creds(struct linux_binprm *bprm) |
1082 | { | 1178 | { |
1083 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | 1179 | if (mutex_lock_interruptible(¤t->signal->cred_guard_mutex)) |
1084 | return -ERESTARTNOINTR; | 1180 | return -ERESTARTNOINTR; |
1085 | 1181 | ||
1086 | bprm->cred = prepare_exec_creds(); | 1182 | bprm->cred = prepare_exec_creds(); |
1087 | if (likely(bprm->cred)) | 1183 | if (likely(bprm->cred)) |
1088 | return 0; | 1184 | return 0; |
1089 | 1185 | ||
1090 | mutex_unlock(¤t->cred_guard_mutex); | 1186 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1091 | return -ENOMEM; | 1187 | return -ENOMEM; |
1092 | } | 1188 | } |
1093 | 1189 | ||
@@ -1095,7 +1191,7 @@ void free_bprm(struct linux_binprm *bprm) | |||
1095 | { | 1191 | { |
1096 | free_arg_pages(bprm); | 1192 | free_arg_pages(bprm); |
1097 | if (bprm->cred) { | 1193 | if (bprm->cred) { |
1098 | mutex_unlock(¤t->cred_guard_mutex); | 1194 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1099 | abort_creds(bprm->cred); | 1195 | abort_creds(bprm->cred); |
1100 | } | 1196 | } |
1101 | kfree(bprm); | 1197 | kfree(bprm); |
@@ -1116,13 +1212,13 @@ void install_exec_creds(struct linux_binprm *bprm) | |||
1116 | * credentials; any time after this it may be unlocked. | 1212 | * credentials; any time after this it may be unlocked. |
1117 | */ | 1213 | */ |
1118 | security_bprm_committed_creds(bprm); | 1214 | security_bprm_committed_creds(bprm); |
1119 | mutex_unlock(¤t->cred_guard_mutex); | 1215 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1120 | } | 1216 | } |
1121 | EXPORT_SYMBOL(install_exec_creds); | 1217 | EXPORT_SYMBOL(install_exec_creds); |
1122 | 1218 | ||
1123 | /* | 1219 | /* |
1124 | * determine how safe it is to execute the proposed program | 1220 | * determine how safe it is to execute the proposed program |
1125 | * - the caller must hold current->cred_guard_mutex to protect against | 1221 | * - the caller must hold ->cred_guard_mutex to protect against |
1126 | * PTRACE_ATTACH | 1222 | * PTRACE_ATTACH |
1127 | */ | 1223 | */ |
1128 | int check_unsafe_exec(struct linux_binprm *bprm) | 1224 | int check_unsafe_exec(struct linux_binprm *bprm) |
@@ -1264,10 +1360,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1264 | if (retval) | 1360 | if (retval) |
1265 | return retval; | 1361 | return retval; |
1266 | 1362 | ||
1267 | /* kernel module loader fixup */ | ||
1268 | /* so we don't try to load run modprobe in kernel space. */ | ||
1269 | set_fs(USER_DS); | ||
1270 | |||
1271 | retval = audit_bprm(bprm); | 1363 | retval = audit_bprm(bprm); |
1272 | if (retval) | 1364 | if (retval) |
1273 | return retval; | 1365 | return retval; |
@@ -1333,10 +1425,10 @@ EXPORT_SYMBOL(search_binary_handler); | |||
1333 | /* | 1425 | /* |
1334 | * sys_execve() executes a new program. | 1426 | * sys_execve() executes a new program. |
1335 | */ | 1427 | */ |
1336 | int do_execve(const char * filename, | 1428 | static int do_execve_common(const char *filename, |
1337 | const char __user *const __user *argv, | 1429 | struct user_arg_ptr argv, |
1338 | const char __user *const __user *envp, | 1430 | struct user_arg_ptr envp, |
1339 | struct pt_regs * regs) | 1431 | struct pt_regs *regs) |
1340 | { | 1432 | { |
1341 | struct linux_binprm *bprm; | 1433 | struct linux_binprm *bprm; |
1342 | struct file *file; | 1434 | struct file *file; |
@@ -1404,7 +1496,6 @@ int do_execve(const char * filename, | |||
1404 | if (retval < 0) | 1496 | if (retval < 0) |
1405 | goto out; | 1497 | goto out; |
1406 | 1498 | ||
1407 | current->flags &= ~PF_KTHREAD; | ||
1408 | retval = search_binary_handler(bprm,regs); | 1499 | retval = search_binary_handler(bprm,regs); |
1409 | if (retval < 0) | 1500 | if (retval < 0) |
1410 | goto out; | 1501 | goto out; |
@@ -1419,8 +1510,10 @@ int do_execve(const char * filename, | |||
1419 | return retval; | 1510 | return retval; |
1420 | 1511 | ||
1421 | out: | 1512 | out: |
1422 | if (bprm->mm) | 1513 | if (bprm->mm) { |
1423 | mmput (bprm->mm); | 1514 | acct_arg_size(bprm, 0); |
1515 | mmput(bprm->mm); | ||
1516 | } | ||
1424 | 1517 | ||
1425 | out_file: | 1518 | out_file: |
1426 | if (bprm->file) { | 1519 | if (bprm->file) { |
@@ -1443,6 +1536,34 @@ out_ret: | |||
1443 | return retval; | 1536 | return retval; |
1444 | } | 1537 | } |
1445 | 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 | |||
1446 | void set_binfmt(struct linux_binfmt *new) | 1567 | void set_binfmt(struct linux_binfmt *new) |
1447 | { | 1568 | { |
1448 | struct mm_struct *mm = current->mm; | 1569 | struct mm_struct *mm = current->mm; |
@@ -1457,127 +1578,186 @@ void set_binfmt(struct linux_binfmt *new) | |||
1457 | 1578 | ||
1458 | EXPORT_SYMBOL(set_binfmt); | 1579 | EXPORT_SYMBOL(set_binfmt); |
1459 | 1580 | ||
1581 | static int expand_corename(struct core_name *cn) | ||
1582 | { | ||
1583 | char *old_corename = cn->corename; | ||
1584 | |||
1585 | cn->size = CORENAME_MAX_SIZE * atomic_inc_return(&call_count); | ||
1586 | cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL); | ||
1587 | |||
1588 | if (!cn->corename) { | ||
1589 | kfree(old_corename); | ||
1590 | return -ENOMEM; | ||
1591 | } | ||
1592 | |||
1593 | return 0; | ||
1594 | } | ||
1595 | |||
1596 | static int cn_printf(struct core_name *cn, const char *fmt, ...) | ||
1597 | { | ||
1598 | char *cur; | ||
1599 | int need; | ||
1600 | int ret; | ||
1601 | va_list arg; | ||
1602 | |||
1603 | va_start(arg, fmt); | ||
1604 | need = vsnprintf(NULL, 0, fmt, arg); | ||
1605 | va_end(arg); | ||
1606 | |||
1607 | if (likely(need < cn->size - cn->used - 1)) | ||
1608 | goto out_printf; | ||
1609 | |||
1610 | ret = expand_corename(cn); | ||
1611 | if (ret) | ||
1612 | goto expand_fail; | ||
1613 | |||
1614 | out_printf: | ||
1615 | cur = cn->corename + cn->used; | ||
1616 | va_start(arg, fmt); | ||
1617 | vsnprintf(cur, need + 1, fmt, arg); | ||
1618 | va_end(arg); | ||
1619 | cn->used += need; | ||
1620 | return 0; | ||
1621 | |||
1622 | expand_fail: | ||
1623 | return ret; | ||
1624 | } | ||
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 | |||
1460 | /* format_corename will inspect the pattern parameter, and output a | 1661 | /* format_corename will inspect the pattern parameter, and output a |
1461 | * name into corename, which must have space for at least | 1662 | * name into corename, which must have space for at least |
1462 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1663 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
1463 | */ | 1664 | */ |
1464 | static int format_corename(char *corename, long signr) | 1665 | static int format_corename(struct core_name *cn, long signr) |
1465 | { | 1666 | { |
1466 | const struct cred *cred = current_cred(); | 1667 | const struct cred *cred = current_cred(); |
1467 | const char *pat_ptr = core_pattern; | 1668 | const char *pat_ptr = core_pattern; |
1468 | int ispipe = (*pat_ptr == '|'); | 1669 | int ispipe = (*pat_ptr == '|'); |
1469 | char *out_ptr = corename; | ||
1470 | char *const out_end = corename + CORENAME_MAX_SIZE; | ||
1471 | int rc; | ||
1472 | int pid_in_pattern = 0; | 1670 | int pid_in_pattern = 0; |
1671 | int err = 0; | ||
1672 | |||
1673 | cn->size = CORENAME_MAX_SIZE * atomic_read(&call_count); | ||
1674 | cn->corename = kmalloc(cn->size, GFP_KERNEL); | ||
1675 | cn->used = 0; | ||
1676 | |||
1677 | if (!cn->corename) | ||
1678 | return -ENOMEM; | ||
1473 | 1679 | ||
1474 | /* Repeat as long as we have more pattern to process and more output | 1680 | /* Repeat as long as we have more pattern to process and more output |
1475 | space */ | 1681 | space */ |
1476 | while (*pat_ptr) { | 1682 | while (*pat_ptr) { |
1477 | if (*pat_ptr != '%') { | 1683 | if (*pat_ptr != '%') { |
1478 | if (out_ptr == out_end) | 1684 | if (*pat_ptr == 0) |
1479 | goto out; | 1685 | goto out; |
1480 | *out_ptr++ = *pat_ptr++; | 1686 | err = cn_printf(cn, "%c", *pat_ptr++); |
1481 | } else { | 1687 | } else { |
1482 | switch (*++pat_ptr) { | 1688 | switch (*++pat_ptr) { |
1689 | /* single % at the end, drop that */ | ||
1483 | case 0: | 1690 | case 0: |
1484 | goto out; | 1691 | goto out; |
1485 | /* Double percent, output one percent */ | 1692 | /* Double percent, output one percent */ |
1486 | case '%': | 1693 | case '%': |
1487 | if (out_ptr == out_end) | 1694 | err = cn_printf(cn, "%c", '%'); |
1488 | goto out; | ||
1489 | *out_ptr++ = '%'; | ||
1490 | break; | 1695 | break; |
1491 | /* pid */ | 1696 | /* pid */ |
1492 | case 'p': | 1697 | case 'p': |
1493 | pid_in_pattern = 1; | 1698 | pid_in_pattern = 1; |
1494 | rc = snprintf(out_ptr, out_end - out_ptr, | 1699 | err = cn_printf(cn, "%d", |
1495 | "%d", task_tgid_vnr(current)); | 1700 | task_tgid_vnr(current)); |
1496 | if (rc > out_end - out_ptr) | ||
1497 | goto out; | ||
1498 | out_ptr += rc; | ||
1499 | break; | 1701 | break; |
1500 | /* uid */ | 1702 | /* uid */ |
1501 | case 'u': | 1703 | case 'u': |
1502 | rc = snprintf(out_ptr, out_end - out_ptr, | 1704 | err = cn_printf(cn, "%d", cred->uid); |
1503 | "%d", cred->uid); | ||
1504 | if (rc > out_end - out_ptr) | ||
1505 | goto out; | ||
1506 | out_ptr += rc; | ||
1507 | break; | 1705 | break; |
1508 | /* gid */ | 1706 | /* gid */ |
1509 | case 'g': | 1707 | case 'g': |
1510 | rc = snprintf(out_ptr, out_end - out_ptr, | 1708 | err = cn_printf(cn, "%d", cred->gid); |
1511 | "%d", cred->gid); | ||
1512 | if (rc > out_end - out_ptr) | ||
1513 | goto out; | ||
1514 | out_ptr += rc; | ||
1515 | break; | 1709 | break; |
1516 | /* signal that caused the coredump */ | 1710 | /* signal that caused the coredump */ |
1517 | case 's': | 1711 | case 's': |
1518 | rc = snprintf(out_ptr, out_end - out_ptr, | 1712 | err = cn_printf(cn, "%ld", signr); |
1519 | "%ld", signr); | ||
1520 | if (rc > out_end - out_ptr) | ||
1521 | goto out; | ||
1522 | out_ptr += rc; | ||
1523 | break; | 1713 | break; |
1524 | /* UNIX time of coredump */ | 1714 | /* UNIX time of coredump */ |
1525 | case 't': { | 1715 | case 't': { |
1526 | struct timeval tv; | 1716 | struct timeval tv; |
1527 | do_gettimeofday(&tv); | 1717 | do_gettimeofday(&tv); |
1528 | rc = snprintf(out_ptr, out_end - out_ptr, | 1718 | err = cn_printf(cn, "%lu", tv.tv_sec); |
1529 | "%lu", tv.tv_sec); | ||
1530 | if (rc > out_end - out_ptr) | ||
1531 | goto out; | ||
1532 | out_ptr += rc; | ||
1533 | break; | 1719 | break; |
1534 | } | 1720 | } |
1535 | /* hostname */ | 1721 | /* hostname */ |
1536 | case 'h': | 1722 | case 'h': |
1537 | down_read(&uts_sem); | 1723 | down_read(&uts_sem); |
1538 | rc = snprintf(out_ptr, out_end - out_ptr, | 1724 | err = cn_printf(cn, "%s", |
1539 | "%s", utsname()->nodename); | 1725 | utsname()->nodename); |
1540 | up_read(&uts_sem); | 1726 | up_read(&uts_sem); |
1541 | if (rc > out_end - out_ptr) | ||
1542 | goto out; | ||
1543 | out_ptr += rc; | ||
1544 | break; | 1727 | break; |
1545 | /* executable */ | 1728 | /* executable */ |
1546 | case 'e': | 1729 | case 'e': |
1547 | rc = snprintf(out_ptr, out_end - out_ptr, | 1730 | err = cn_printf(cn, "%s", current->comm); |
1548 | "%s", current->comm); | 1731 | break; |
1549 | if (rc > out_end - out_ptr) | 1732 | case 'E': |
1550 | goto out; | 1733 | err = cn_print_exe_file(cn); |
1551 | out_ptr += rc; | ||
1552 | break; | 1734 | break; |
1553 | /* core limit size */ | 1735 | /* core limit size */ |
1554 | case 'c': | 1736 | case 'c': |
1555 | rc = snprintf(out_ptr, out_end - out_ptr, | 1737 | err = cn_printf(cn, "%lu", |
1556 | "%lu", rlimit(RLIMIT_CORE)); | 1738 | rlimit(RLIMIT_CORE)); |
1557 | if (rc > out_end - out_ptr) | ||
1558 | goto out; | ||
1559 | out_ptr += rc; | ||
1560 | break; | 1739 | break; |
1561 | default: | 1740 | default: |
1562 | break; | 1741 | break; |
1563 | } | 1742 | } |
1564 | ++pat_ptr; | 1743 | ++pat_ptr; |
1565 | } | 1744 | } |
1745 | |||
1746 | if (err) | ||
1747 | return err; | ||
1566 | } | 1748 | } |
1749 | |||
1567 | /* Backward compatibility with core_uses_pid: | 1750 | /* Backward compatibility with core_uses_pid: |
1568 | * | 1751 | * |
1569 | * If core_pattern does not include a %p (as is the default) | 1752 | * If core_pattern does not include a %p (as is the default) |
1570 | * and core_uses_pid is set, then .%pid will be appended to | 1753 | * and core_uses_pid is set, then .%pid will be appended to |
1571 | * the filename. Do not do this for piped commands. */ | 1754 | * the filename. Do not do this for piped commands. */ |
1572 | if (!ispipe && !pid_in_pattern && core_uses_pid) { | 1755 | if (!ispipe && !pid_in_pattern && core_uses_pid) { |
1573 | rc = snprintf(out_ptr, out_end - out_ptr, | 1756 | err = cn_printf(cn, ".%d", task_tgid_vnr(current)); |
1574 | ".%d", task_tgid_vnr(current)); | 1757 | if (err) |
1575 | if (rc > out_end - out_ptr) | 1758 | return err; |
1576 | goto out; | ||
1577 | out_ptr += rc; | ||
1578 | } | 1759 | } |
1579 | out: | 1760 | out: |
1580 | *out_ptr = 0; | ||
1581 | return ispipe; | 1761 | return ispipe; |
1582 | } | 1762 | } |
1583 | 1763 | ||
@@ -1592,6 +1772,7 @@ static int zap_process(struct task_struct *start, int exit_code) | |||
1592 | 1772 | ||
1593 | t = start; | 1773 | t = start; |
1594 | do { | 1774 | do { |
1775 | task_clear_group_stop_pending(t); | ||
1595 | if (t != current && t->mm) { | 1776 | if (t != current && t->mm) { |
1596 | sigaddset(&t->pending.signal, SIGKILL); | 1777 | sigaddset(&t->pending.signal, SIGKILL); |
1597 | signal_wake_up(t, 1); | 1778 | signal_wake_up(t, 1); |
@@ -1808,7 +1989,7 @@ static void wait_for_dump_helpers(struct file *file) | |||
1808 | 1989 | ||
1809 | 1990 | ||
1810 | /* | 1991 | /* |
1811 | * uhm_pipe_setup | 1992 | * umh_pipe_setup |
1812 | * helper function to customize the process used | 1993 | * helper function to customize the process used |
1813 | * to collect the core in userspace. Specifically | 1994 | * to collect the core in userspace. Specifically |
1814 | * 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) |
@@ -1818,7 +1999,7 @@ static void wait_for_dump_helpers(struct file *file) | |||
1818 | * is a special value that we use to trap recursive | 1999 | * is a special value that we use to trap recursive |
1819 | * core dumps | 2000 | * core dumps |
1820 | */ | 2001 | */ |
1821 | static int umh_pipe_setup(struct subprocess_info *info) | 2002 | static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) |
1822 | { | 2003 | { |
1823 | struct file *rp, *wp; | 2004 | struct file *rp, *wp; |
1824 | struct fdtable *fdt; | 2005 | struct fdtable *fdt; |
@@ -1854,7 +2035,7 @@ static int umh_pipe_setup(struct subprocess_info *info) | |||
1854 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 2035 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
1855 | { | 2036 | { |
1856 | struct core_state core_state; | 2037 | struct core_state core_state; |
1857 | char corename[CORENAME_MAX_SIZE + 1]; | 2038 | struct core_name cn; |
1858 | struct mm_struct *mm = current->mm; | 2039 | struct mm_struct *mm = current->mm; |
1859 | struct linux_binfmt * binfmt; | 2040 | struct linux_binfmt * binfmt; |
1860 | const struct cred *old_cred; | 2041 | const struct cred *old_cred; |
@@ -1909,7 +2090,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1909 | */ | 2090 | */ |
1910 | clear_thread_flag(TIF_SIGPENDING); | 2091 | clear_thread_flag(TIF_SIGPENDING); |
1911 | 2092 | ||
1912 | ispipe = format_corename(corename, signr); | 2093 | ispipe = format_corename(&cn, signr); |
2094 | |||
2095 | if (ispipe == -ENOMEM) { | ||
2096 | printk(KERN_WARNING "format_corename failed\n"); | ||
2097 | printk(KERN_WARNING "Aborting core\n"); | ||
2098 | goto fail_corename; | ||
2099 | } | ||
1913 | 2100 | ||
1914 | if (ispipe) { | 2101 | if (ispipe) { |
1915 | int dump_count; | 2102 | int dump_count; |
@@ -1946,7 +2133,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1946 | goto fail_dropcount; | 2133 | goto fail_dropcount; |
1947 | } | 2134 | } |
1948 | 2135 | ||
1949 | helper_argv = argv_split(GFP_KERNEL, corename+1, NULL); | 2136 | helper_argv = argv_split(GFP_KERNEL, cn.corename+1, NULL); |
1950 | if (!helper_argv) { | 2137 | if (!helper_argv) { |
1951 | printk(KERN_WARNING "%s failed to allocate memory\n", | 2138 | printk(KERN_WARNING "%s failed to allocate memory\n", |
1952 | __func__); | 2139 | __func__); |
@@ -1959,7 +2146,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1959 | argv_free(helper_argv); | 2146 | argv_free(helper_argv); |
1960 | if (retval) { | 2147 | if (retval) { |
1961 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 2148 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
1962 | corename); | 2149 | cn.corename); |
1963 | goto close_fail; | 2150 | goto close_fail; |
1964 | } | 2151 | } |
1965 | } else { | 2152 | } else { |
@@ -1968,7 +2155,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1968 | if (cprm.limit < binfmt->min_coredump) | 2155 | if (cprm.limit < binfmt->min_coredump) |
1969 | goto fail_unlock; | 2156 | goto fail_unlock; |
1970 | 2157 | ||
1971 | cprm.file = filp_open(corename, | 2158 | cprm.file = filp_open(cn.corename, |
1972 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 2159 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
1973 | 0600); | 2160 | 0600); |
1974 | if (IS_ERR(cprm.file)) | 2161 | if (IS_ERR(cprm.file)) |
@@ -2010,6 +2197,8 @@ fail_dropcount: | |||
2010 | if (ispipe) | 2197 | if (ispipe) |
2011 | atomic_dec(&core_dump_count); | 2198 | atomic_dec(&core_dump_count); |
2012 | fail_unlock: | 2199 | fail_unlock: |
2200 | kfree(cn.corename); | ||
2201 | fail_corename: | ||
2013 | coredump_finish(mm); | 2202 | coredump_finish(mm); |
2014 | revert_creds(old_cred); | 2203 | revert_creds(old_cred); |
2015 | fail_creds: | 2204 | fail_creds: |