diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 264 |
1 files changed, 176 insertions, 88 deletions
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
| 29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
| 30 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
| 31 | #include <linux/smp_lock.h> | ||
| 32 | #include <linux/swap.h> | 31 | #include <linux/swap.h> |
| 33 | #include <linux/string.h> | 32 | #include <linux/string.h> |
| 34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| @@ -55,6 +54,7 @@ | |||
| 55 | #include <linux/fsnotify.h> | 54 | #include <linux/fsnotify.h> |
| 56 | #include <linux/fs_struct.h> | 55 | #include <linux/fs_struct.h> |
| 57 | #include <linux/pipe_fs_i.h> | 56 | #include <linux/pipe_fs_i.h> |
| 57 | #include <linux/oom.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> |
| @@ -66,6 +66,12 @@ char core_pattern[CORENAME_MAX_SIZE] = "core"; | |||
| 66 | unsigned int core_pipe_limit; | 66 | unsigned int core_pipe_limit; |
| 67 | int suid_dumpable = 0; | 67 | int suid_dumpable = 0; |
| 68 | 68 | ||
| 69 | struct core_name { | ||
| 70 | char *corename; | ||
| 71 | int used, size; | ||
| 72 | }; | ||
| 73 | static atomic_t call_count = ATOMIC_INIT(1); | ||
| 74 | |||
| 69 | /* The maximal length of core_pattern is also specified in sysctl.c */ | 75 | /* The maximal length of core_pattern is also specified in sysctl.c */ |
| 70 | 76 | ||
| 71 | static LIST_HEAD(formats); | 77 | static LIST_HEAD(formats); |
| @@ -129,7 +135,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
| 129 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) | 135 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) |
| 130 | goto exit; | 136 | goto exit; |
| 131 | 137 | ||
| 132 | fsnotify_open(file->f_path.dentry); | 138 | fsnotify_open(file); |
| 133 | 139 | ||
| 134 | error = -ENOEXEC; | 140 | error = -ENOEXEC; |
| 135 | if(file->f_op) { | 141 | if(file->f_op) { |
| @@ -362,13 +368,13 @@ err: | |||
| 362 | /* | 368 | /* |
| 363 | * count() counts the number of strings in array ARGV. | 369 | * count() counts the number of strings in array ARGV. |
| 364 | */ | 370 | */ |
| 365 | static int count(char __user * __user * argv, int max) | 371 | static int count(const char __user * const __user * argv, int max) |
| 366 | { | 372 | { |
| 367 | int i = 0; | 373 | int i = 0; |
| 368 | 374 | ||
| 369 | if (argv != NULL) { | 375 | if (argv != NULL) { |
| 370 | for (;;) { | 376 | for (;;) { |
| 371 | char __user * p; | 377 | const char __user * p; |
| 372 | 378 | ||
| 373 | if (get_user(p, argv)) | 379 | if (get_user(p, argv)) |
| 374 | return -EFAULT; | 380 | return -EFAULT; |
| @@ -377,6 +383,9 @@ static int count(char __user * __user * argv, int max) | |||
| 377 | argv++; | 383 | argv++; |
| 378 | if (i++ >= max) | 384 | if (i++ >= max) |
| 379 | return -E2BIG; | 385 | return -E2BIG; |
| 386 | |||
| 387 | if (fatal_signal_pending(current)) | ||
| 388 | return -ERESTARTNOHAND; | ||
| 380 | cond_resched(); | 389 | cond_resched(); |
| 381 | } | 390 | } |
| 382 | } | 391 | } |
| @@ -388,7 +397,7 @@ static int count(char __user * __user * argv, int max) | |||
| 388 | * processes's memory to the new process's stack. The call to get_user_pages() | 397 | * processes's memory to the new process's stack. The call to get_user_pages() |
| 389 | * ensures the destination page is created and not swapped out. | 398 | * ensures the destination page is created and not swapped out. |
| 390 | */ | 399 | */ |
| 391 | static int copy_strings(int argc, char __user * __user * argv, | 400 | static int copy_strings(int argc, const char __user *const __user *argv, |
| 392 | struct linux_binprm *bprm) | 401 | struct linux_binprm *bprm) |
| 393 | { | 402 | { |
| 394 | struct page *kmapped_page = NULL; | 403 | struct page *kmapped_page = NULL; |
| @@ -397,7 +406,7 @@ static int copy_strings(int argc, char __user * __user * argv, | |||
| 397 | int ret; | 406 | int ret; |
| 398 | 407 | ||
| 399 | while (argc-- > 0) { | 408 | while (argc-- > 0) { |
| 400 | char __user *str; | 409 | const char __user *str; |
| 401 | int len; | 410 | int len; |
| 402 | unsigned long pos; | 411 | unsigned long pos; |
| 403 | 412 | ||
| @@ -420,6 +429,12 @@ static int copy_strings(int argc, char __user * __user * argv, | |||
| 420 | while (len > 0) { | 429 | while (len > 0) { |
| 421 | int offset, bytes_to_copy; | 430 | int offset, bytes_to_copy; |
| 422 | 431 | ||
| 432 | if (fatal_signal_pending(current)) { | ||
| 433 | ret = -ERESTARTNOHAND; | ||
| 434 | goto out; | ||
| 435 | } | ||
| 436 | cond_resched(); | ||
| 437 | |||
| 423 | offset = pos % PAGE_SIZE; | 438 | offset = pos % PAGE_SIZE; |
| 424 | if (offset == 0) | 439 | if (offset == 0) |
| 425 | offset = PAGE_SIZE; | 440 | offset = PAGE_SIZE; |
| @@ -471,12 +486,13 @@ out: | |||
| 471 | /* | 486 | /* |
| 472 | * Like copy_strings, but get argv and its values from kernel memory. | 487 | * Like copy_strings, but get argv and its values from kernel memory. |
| 473 | */ | 488 | */ |
| 474 | int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm) | 489 | int copy_strings_kernel(int argc, const char *const *argv, |
| 490 | struct linux_binprm *bprm) | ||
| 475 | { | 491 | { |
| 476 | int r; | 492 | int r; |
| 477 | mm_segment_t oldfs = get_fs(); | 493 | mm_segment_t oldfs = get_fs(); |
| 478 | set_fs(KERNEL_DS); | 494 | set_fs(KERNEL_DS); |
| 479 | r = copy_strings(argc, (char __user * __user *)argv, bprm); | 495 | r = copy_strings(argc, (const char __user *const __user *)argv, bprm); |
| 480 | set_fs(oldfs); | 496 | set_fs(oldfs); |
| 481 | return r; | 497 | return r; |
| 482 | } | 498 | } |
| @@ -594,6 +610,11 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
| 594 | #else | 610 | #else |
| 595 | stack_top = arch_align_stack(stack_top); | 611 | stack_top = arch_align_stack(stack_top); |
| 596 | stack_top = PAGE_ALIGN(stack_top); | 612 | stack_top = PAGE_ALIGN(stack_top); |
| 613 | |||
| 614 | if (unlikely(stack_top < mmap_min_addr) || | ||
| 615 | unlikely(vma->vm_end - vma->vm_start >= stack_top - mmap_min_addr)) | ||
| 616 | return -ENOMEM; | ||
| 617 | |||
| 597 | stack_shift = vma->vm_end - stack_top; | 618 | stack_shift = vma->vm_end - stack_top; |
| 598 | 619 | ||
| 599 | bprm->p -= stack_shift; | 620 | bprm->p -= stack_shift; |
| @@ -653,6 +674,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
| 653 | else | 674 | else |
| 654 | stack_base = vma->vm_start - stack_expand; | 675 | stack_base = vma->vm_start - stack_expand; |
| 655 | #endif | 676 | #endif |
| 677 | current->mm->start_stack = bprm->p; | ||
| 656 | ret = expand_stack(vma, stack_base); | 678 | ret = expand_stack(vma, stack_base); |
| 657 | if (ret) | 679 | if (ret) |
| 658 | ret = -EFAULT; | 680 | ret = -EFAULT; |
| @@ -683,7 +705,7 @@ struct file *open_exec(const char *name) | |||
| 683 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) | 705 | if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) |
| 684 | goto exit; | 706 | goto exit; |
| 685 | 707 | ||
| 686 | fsnotify_open(file->f_path.dentry); | 708 | fsnotify_open(file); |
| 687 | 709 | ||
| 688 | err = deny_write_access(file); | 710 | err = deny_write_access(file); |
| 689 | if (err) | 711 | if (err) |
| @@ -744,6 +766,10 @@ static int exec_mmap(struct mm_struct *mm) | |||
| 744 | tsk->mm = mm; | 766 | tsk->mm = mm; |
| 745 | tsk->active_mm = mm; | 767 | tsk->active_mm = mm; |
| 746 | activate_mm(active_mm, mm); | 768 | activate_mm(active_mm, mm); |
| 769 | if (old_mm && tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) { | ||
| 770 | atomic_dec(&old_mm->oom_disable_count); | ||
| 771 | atomic_inc(&tsk->mm->oom_disable_count); | ||
| 772 | } | ||
| 747 | task_unlock(tsk); | 773 | task_unlock(tsk); |
| 748 | arch_pick_mmap_layout(mm); | 774 | arch_pick_mmap_layout(mm); |
| 749 | if (old_mm) { | 775 | if (old_mm) { |
| @@ -983,7 +1009,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 983 | 1009 | ||
| 984 | bprm->mm = NULL; /* We're using it now */ | 1010 | bprm->mm = NULL; /* We're using it now */ |
| 985 | 1011 | ||
| 986 | current->flags &= ~PF_RANDOMIZE; | 1012 | current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD); |
| 987 | flush_thread(); | 1013 | flush_thread(); |
| 988 | current->personality &= ~bprm->per_clear; | 1014 | current->personality &= ~bprm->per_clear; |
| 989 | 1015 | ||
| @@ -997,7 +1023,7 @@ EXPORT_SYMBOL(flush_old_exec); | |||
| 997 | void setup_new_exec(struct linux_binprm * bprm) | 1023 | void setup_new_exec(struct linux_binprm * bprm) |
| 998 | { | 1024 | { |
| 999 | int i, ch; | 1025 | int i, ch; |
| 1000 | char * name; | 1026 | const char *name; |
| 1001 | char tcomm[sizeof(current->comm)]; | 1027 | char tcomm[sizeof(current->comm)]; |
| 1002 | 1028 | ||
| 1003 | arch_pick_mmap_layout(current->mm); | 1029 | arch_pick_mmap_layout(current->mm); |
| @@ -1063,14 +1089,14 @@ EXPORT_SYMBOL(setup_new_exec); | |||
| 1063 | */ | 1089 | */ |
| 1064 | int prepare_bprm_creds(struct linux_binprm *bprm) | 1090 | int prepare_bprm_creds(struct linux_binprm *bprm) |
| 1065 | { | 1091 | { |
| 1066 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | 1092 | if (mutex_lock_interruptible(¤t->signal->cred_guard_mutex)) |
| 1067 | return -ERESTARTNOINTR; | 1093 | return -ERESTARTNOINTR; |
| 1068 | 1094 | ||
| 1069 | bprm->cred = prepare_exec_creds(); | 1095 | bprm->cred = prepare_exec_creds(); |
| 1070 | if (likely(bprm->cred)) | 1096 | if (likely(bprm->cred)) |
| 1071 | return 0; | 1097 | return 0; |
| 1072 | 1098 | ||
| 1073 | mutex_unlock(¤t->cred_guard_mutex); | 1099 | mutex_unlock(¤t->signal->cred_guard_mutex); |
| 1074 | return -ENOMEM; | 1100 | return -ENOMEM; |
| 1075 | } | 1101 | } |
| 1076 | 1102 | ||
| @@ -1078,7 +1104,7 @@ void free_bprm(struct linux_binprm *bprm) | |||
| 1078 | { | 1104 | { |
| 1079 | free_arg_pages(bprm); | 1105 | free_arg_pages(bprm); |
| 1080 | if (bprm->cred) { | 1106 | if (bprm->cred) { |
| 1081 | mutex_unlock(¤t->cred_guard_mutex); | 1107 | mutex_unlock(¤t->signal->cred_guard_mutex); |
| 1082 | abort_creds(bprm->cred); | 1108 | abort_creds(bprm->cred); |
| 1083 | } | 1109 | } |
| 1084 | kfree(bprm); | 1110 | kfree(bprm); |
| @@ -1099,13 +1125,13 @@ void install_exec_creds(struct linux_binprm *bprm) | |||
| 1099 | * credentials; any time after this it may be unlocked. | 1125 | * credentials; any time after this it may be unlocked. |
| 1100 | */ | 1126 | */ |
| 1101 | security_bprm_committed_creds(bprm); | 1127 | security_bprm_committed_creds(bprm); |
| 1102 | mutex_unlock(¤t->cred_guard_mutex); | 1128 | mutex_unlock(¤t->signal->cred_guard_mutex); |
| 1103 | } | 1129 | } |
| 1104 | EXPORT_SYMBOL(install_exec_creds); | 1130 | EXPORT_SYMBOL(install_exec_creds); |
| 1105 | 1131 | ||
| 1106 | /* | 1132 | /* |
| 1107 | * determine how safe it is to execute the proposed program | 1133 | * determine how safe it is to execute the proposed program |
| 1108 | * - the caller must hold current->cred_guard_mutex to protect against | 1134 | * - the caller must hold ->cred_guard_mutex to protect against |
| 1109 | * PTRACE_ATTACH | 1135 | * PTRACE_ATTACH |
| 1110 | */ | 1136 | */ |
| 1111 | int check_unsafe_exec(struct linux_binprm *bprm) | 1137 | int check_unsafe_exec(struct linux_binprm *bprm) |
| @@ -1117,7 +1143,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) | |||
| 1117 | bprm->unsafe = tracehook_unsafe_exec(p); | 1143 | bprm->unsafe = tracehook_unsafe_exec(p); |
| 1118 | 1144 | ||
| 1119 | n_fs = 1; | 1145 | n_fs = 1; |
| 1120 | write_lock(&p->fs->lock); | 1146 | spin_lock(&p->fs->lock); |
| 1121 | rcu_read_lock(); | 1147 | rcu_read_lock(); |
| 1122 | for (t = next_thread(p); t != p; t = next_thread(t)) { | 1148 | for (t = next_thread(p); t != p; t = next_thread(t)) { |
| 1123 | if (t->fs == p->fs) | 1149 | if (t->fs == p->fs) |
| @@ -1134,7 +1160,7 @@ int check_unsafe_exec(struct linux_binprm *bprm) | |||
| 1134 | res = 1; | 1160 | res = 1; |
| 1135 | } | 1161 | } |
| 1136 | } | 1162 | } |
| 1137 | write_unlock(&p->fs->lock); | 1163 | spin_unlock(&p->fs->lock); |
| 1138 | 1164 | ||
| 1139 | return res; | 1165 | return res; |
| 1140 | } | 1166 | } |
| @@ -1316,9 +1342,9 @@ EXPORT_SYMBOL(search_binary_handler); | |||
| 1316 | /* | 1342 | /* |
| 1317 | * sys_execve() executes a new program. | 1343 | * sys_execve() executes a new program. |
| 1318 | */ | 1344 | */ |
| 1319 | int do_execve(char * filename, | 1345 | int do_execve(const char * filename, |
| 1320 | char __user *__user *argv, | 1346 | const char __user *const __user *argv, |
| 1321 | char __user *__user *envp, | 1347 | const char __user *const __user *envp, |
| 1322 | struct pt_regs * regs) | 1348 | struct pt_regs * regs) |
| 1323 | { | 1349 | { |
| 1324 | struct linux_binprm *bprm; | 1350 | struct linux_binprm *bprm; |
| @@ -1386,7 +1412,6 @@ int do_execve(char * filename, | |||
| 1386 | if (retval < 0) | 1412 | if (retval < 0) |
| 1387 | goto out; | 1413 | goto out; |
| 1388 | 1414 | ||
| 1389 | current->flags &= ~PF_KTHREAD; | ||
| 1390 | retval = search_binary_handler(bprm,regs); | 1415 | retval = search_binary_handler(bprm,regs); |
| 1391 | if (retval < 0) | 1416 | if (retval < 0) |
| 1392 | goto out; | 1417 | goto out; |
| @@ -1439,127 +1464,148 @@ void set_binfmt(struct linux_binfmt *new) | |||
| 1439 | 1464 | ||
| 1440 | EXPORT_SYMBOL(set_binfmt); | 1465 | EXPORT_SYMBOL(set_binfmt); |
| 1441 | 1466 | ||
| 1467 | static int expand_corename(struct core_name *cn) | ||
| 1468 | { | ||
| 1469 | char *old_corename = cn->corename; | ||
| 1470 | |||
| 1471 | cn->size = CORENAME_MAX_SIZE * atomic_inc_return(&call_count); | ||
| 1472 | cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL); | ||
| 1473 | |||
| 1474 | if (!cn->corename) { | ||
| 1475 | kfree(old_corename); | ||
| 1476 | return -ENOMEM; | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | return 0; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | static int cn_printf(struct core_name *cn, const char *fmt, ...) | ||
| 1483 | { | ||
| 1484 | char *cur; | ||
| 1485 | int need; | ||
| 1486 | int ret; | ||
| 1487 | va_list arg; | ||
| 1488 | |||
| 1489 | va_start(arg, fmt); | ||
| 1490 | need = vsnprintf(NULL, 0, fmt, arg); | ||
| 1491 | va_end(arg); | ||
| 1492 | |||
| 1493 | if (likely(need < cn->size - cn->used - 1)) | ||
| 1494 | goto out_printf; | ||
| 1495 | |||
| 1496 | ret = expand_corename(cn); | ||
| 1497 | if (ret) | ||
| 1498 | goto expand_fail; | ||
| 1499 | |||
| 1500 | out_printf: | ||
| 1501 | cur = cn->corename + cn->used; | ||
| 1502 | va_start(arg, fmt); | ||
| 1503 | vsnprintf(cur, need + 1, fmt, arg); | ||
| 1504 | va_end(arg); | ||
| 1505 | cn->used += need; | ||
| 1506 | return 0; | ||
| 1507 | |||
| 1508 | expand_fail: | ||
| 1509 | return ret; | ||
| 1510 | } | ||
| 1511 | |||
| 1442 | /* format_corename will inspect the pattern parameter, and output a | 1512 | /* format_corename will inspect the pattern parameter, and output a |
| 1443 | * name into corename, which must have space for at least | 1513 | * name into corename, which must have space for at least |
| 1444 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. | 1514 | * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. |
| 1445 | */ | 1515 | */ |
| 1446 | static int format_corename(char *corename, long signr) | 1516 | static int format_corename(struct core_name *cn, long signr) |
| 1447 | { | 1517 | { |
| 1448 | const struct cred *cred = current_cred(); | 1518 | const struct cred *cred = current_cred(); |
| 1449 | const char *pat_ptr = core_pattern; | 1519 | const char *pat_ptr = core_pattern; |
| 1450 | int ispipe = (*pat_ptr == '|'); | 1520 | int ispipe = (*pat_ptr == '|'); |
| 1451 | char *out_ptr = corename; | ||
| 1452 | char *const out_end = corename + CORENAME_MAX_SIZE; | ||
| 1453 | int rc; | ||
| 1454 | int pid_in_pattern = 0; | 1521 | int pid_in_pattern = 0; |
| 1522 | int err = 0; | ||
| 1523 | |||
| 1524 | cn->size = CORENAME_MAX_SIZE * atomic_read(&call_count); | ||
| 1525 | cn->corename = kmalloc(cn->size, GFP_KERNEL); | ||
| 1526 | cn->used = 0; | ||
| 1527 | |||
| 1528 | if (!cn->corename) | ||
| 1529 | return -ENOMEM; | ||
| 1455 | 1530 | ||
| 1456 | /* Repeat as long as we have more pattern to process and more output | 1531 | /* Repeat as long as we have more pattern to process and more output |
| 1457 | space */ | 1532 | space */ |
| 1458 | while (*pat_ptr) { | 1533 | while (*pat_ptr) { |
| 1459 | if (*pat_ptr != '%') { | 1534 | if (*pat_ptr != '%') { |
| 1460 | if (out_ptr == out_end) | 1535 | if (*pat_ptr == 0) |
| 1461 | goto out; | 1536 | goto out; |
| 1462 | *out_ptr++ = *pat_ptr++; | 1537 | err = cn_printf(cn, "%c", *pat_ptr++); |
| 1463 | } else { | 1538 | } else { |
| 1464 | switch (*++pat_ptr) { | 1539 | switch (*++pat_ptr) { |
| 1540 | /* single % at the end, drop that */ | ||
| 1465 | case 0: | 1541 | case 0: |
| 1466 | goto out; | 1542 | goto out; |
| 1467 | /* Double percent, output one percent */ | 1543 | /* Double percent, output one percent */ |
| 1468 | case '%': | 1544 | case '%': |
| 1469 | if (out_ptr == out_end) | 1545 | err = cn_printf(cn, "%c", '%'); |
| 1470 | goto out; | ||
| 1471 | *out_ptr++ = '%'; | ||
| 1472 | break; | 1546 | break; |
| 1473 | /* pid */ | 1547 | /* pid */ |
| 1474 | case 'p': | 1548 | case 'p': |
| 1475 | pid_in_pattern = 1; | 1549 | pid_in_pattern = 1; |
| 1476 | rc = snprintf(out_ptr, out_end - out_ptr, | 1550 | err = cn_printf(cn, "%d", |
| 1477 | "%d", task_tgid_vnr(current)); | 1551 | task_tgid_vnr(current)); |
| 1478 | if (rc > out_end - out_ptr) | ||
| 1479 | goto out; | ||
| 1480 | out_ptr += rc; | ||
| 1481 | break; | 1552 | break; |
| 1482 | /* uid */ | 1553 | /* uid */ |
| 1483 | case 'u': | 1554 | case 'u': |
| 1484 | rc = snprintf(out_ptr, out_end - out_ptr, | 1555 | err = cn_printf(cn, "%d", cred->uid); |
| 1485 | "%d", cred->uid); | ||
| 1486 | if (rc > out_end - out_ptr) | ||
| 1487 | goto out; | ||
| 1488 | out_ptr += rc; | ||
| 1489 | break; | 1556 | break; |
| 1490 | /* gid */ | 1557 | /* gid */ |
| 1491 | case 'g': | 1558 | case 'g': |
| 1492 | rc = snprintf(out_ptr, out_end - out_ptr, | 1559 | err = cn_printf(cn, "%d", cred->gid); |
| 1493 | "%d", cred->gid); | ||
| 1494 | if (rc > out_end - out_ptr) | ||
| 1495 | goto out; | ||
| 1496 | out_ptr += rc; | ||
| 1497 | break; | 1560 | break; |
| 1498 | /* signal that caused the coredump */ | 1561 | /* signal that caused the coredump */ |
| 1499 | case 's': | 1562 | case 's': |
| 1500 | rc = snprintf(out_ptr, out_end - out_ptr, | 1563 | err = cn_printf(cn, "%ld", signr); |
| 1501 | "%ld", signr); | ||
| 1502 | if (rc > out_end - out_ptr) | ||
| 1503 | goto out; | ||
| 1504 | out_ptr += rc; | ||
| 1505 | break; | 1564 | break; |
| 1506 | /* UNIX time of coredump */ | 1565 | /* UNIX time of coredump */ |
| 1507 | case 't': { | 1566 | case 't': { |
| 1508 | struct timeval tv; | 1567 | struct timeval tv; |
| 1509 | do_gettimeofday(&tv); | 1568 | do_gettimeofday(&tv); |
| 1510 | rc = snprintf(out_ptr, out_end - out_ptr, | 1569 | err = cn_printf(cn, "%lu", tv.tv_sec); |
| 1511 | "%lu", tv.tv_sec); | ||
| 1512 | if (rc > out_end - out_ptr) | ||
| 1513 | goto out; | ||
| 1514 | out_ptr += rc; | ||
| 1515 | break; | 1570 | break; |
| 1516 | } | 1571 | } |
| 1517 | /* hostname */ | 1572 | /* hostname */ |
| 1518 | case 'h': | 1573 | case 'h': |
| 1519 | down_read(&uts_sem); | 1574 | down_read(&uts_sem); |
| 1520 | rc = snprintf(out_ptr, out_end - out_ptr, | 1575 | err = cn_printf(cn, "%s", |
| 1521 | "%s", utsname()->nodename); | 1576 | utsname()->nodename); |
| 1522 | up_read(&uts_sem); | 1577 | up_read(&uts_sem); |
| 1523 | if (rc > out_end - out_ptr) | ||
| 1524 | goto out; | ||
| 1525 | out_ptr += rc; | ||
| 1526 | break; | 1578 | break; |
| 1527 | /* executable */ | 1579 | /* executable */ |
| 1528 | case 'e': | 1580 | case 'e': |
| 1529 | rc = snprintf(out_ptr, out_end - out_ptr, | 1581 | err = cn_printf(cn, "%s", current->comm); |
| 1530 | "%s", current->comm); | ||
| 1531 | if (rc > out_end - out_ptr) | ||
| 1532 | goto out; | ||
| 1533 | out_ptr += rc; | ||
| 1534 | break; | 1582 | break; |
| 1535 | /* core limit size */ | 1583 | /* core limit size */ |
| 1536 | case 'c': | 1584 | case 'c': |
| 1537 | rc = snprintf(out_ptr, out_end - out_ptr, | 1585 | err = cn_printf(cn, "%lu", |
| 1538 | "%lu", rlimit(RLIMIT_CORE)); | 1586 | rlimit(RLIMIT_CORE)); |
| 1539 | if (rc > out_end - out_ptr) | ||
| 1540 | goto out; | ||
| 1541 | out_ptr += rc; | ||
| 1542 | break; | 1587 | break; |
| 1543 | default: | 1588 | default: |
| 1544 | break; | 1589 | break; |
| 1545 | } | 1590 | } |
| 1546 | ++pat_ptr; | 1591 | ++pat_ptr; |
| 1547 | } | 1592 | } |
| 1593 | |||
| 1594 | if (err) | ||
| 1595 | return err; | ||
| 1548 | } | 1596 | } |
| 1597 | |||
| 1549 | /* Backward compatibility with core_uses_pid: | 1598 | /* Backward compatibility with core_uses_pid: |
| 1550 | * | 1599 | * |
| 1551 | * If core_pattern does not include a %p (as is the default) | 1600 | * If core_pattern does not include a %p (as is the default) |
| 1552 | * and core_uses_pid is set, then .%pid will be appended to | 1601 | * and core_uses_pid is set, then .%pid will be appended to |
| 1553 | * the filename. Do not do this for piped commands. */ | 1602 | * the filename. Do not do this for piped commands. */ |
| 1554 | if (!ispipe && !pid_in_pattern && core_uses_pid) { | 1603 | if (!ispipe && !pid_in_pattern && core_uses_pid) { |
| 1555 | rc = snprintf(out_ptr, out_end - out_ptr, | 1604 | err = cn_printf(cn, ".%d", task_tgid_vnr(current)); |
| 1556 | ".%d", task_tgid_vnr(current)); | 1605 | if (err) |
| 1557 | if (rc > out_end - out_ptr) | 1606 | return err; |
| 1558 | goto out; | ||
| 1559 | out_ptr += rc; | ||
| 1560 | } | 1607 | } |
| 1561 | out: | 1608 | out: |
| 1562 | *out_ptr = 0; | ||
| 1563 | return ispipe; | 1609 | return ispipe; |
| 1564 | } | 1610 | } |
| 1565 | 1611 | ||
| @@ -1836,7 +1882,7 @@ static int umh_pipe_setup(struct subprocess_info *info) | |||
| 1836 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) | 1882 | void do_coredump(long signr, int exit_code, struct pt_regs *regs) |
| 1837 | { | 1883 | { |
| 1838 | struct core_state core_state; | 1884 | struct core_state core_state; |
| 1839 | char corename[CORENAME_MAX_SIZE + 1]; | 1885 | struct core_name cn; |
| 1840 | struct mm_struct *mm = current->mm; | 1886 | struct mm_struct *mm = current->mm; |
| 1841 | struct linux_binfmt * binfmt; | 1887 | struct linux_binfmt * binfmt; |
| 1842 | const struct cred *old_cred; | 1888 | const struct cred *old_cred; |
| @@ -1891,13 +1937,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1891 | */ | 1937 | */ |
| 1892 | clear_thread_flag(TIF_SIGPENDING); | 1938 | clear_thread_flag(TIF_SIGPENDING); |
| 1893 | 1939 | ||
| 1894 | /* | 1940 | ispipe = format_corename(&cn, signr); |
| 1895 | * lock_kernel() because format_corename() is controlled by sysctl, which | 1941 | |
| 1896 | * uses lock_kernel() | 1942 | if (ispipe == -ENOMEM) { |
| 1897 | */ | 1943 | printk(KERN_WARNING "format_corename failed\n"); |
| 1898 | lock_kernel(); | 1944 | printk(KERN_WARNING "Aborting core\n"); |
| 1899 | ispipe = format_corename(corename, signr); | 1945 | goto fail_corename; |
| 1900 | unlock_kernel(); | 1946 | } |
| 1901 | 1947 | ||
| 1902 | if (ispipe) { | 1948 | if (ispipe) { |
| 1903 | int dump_count; | 1949 | int dump_count; |
| @@ -1934,7 +1980,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1934 | goto fail_dropcount; | 1980 | goto fail_dropcount; |
| 1935 | } | 1981 | } |
| 1936 | 1982 | ||
| 1937 | helper_argv = argv_split(GFP_KERNEL, corename+1, NULL); | 1983 | helper_argv = argv_split(GFP_KERNEL, cn.corename+1, NULL); |
| 1938 | if (!helper_argv) { | 1984 | if (!helper_argv) { |
| 1939 | printk(KERN_WARNING "%s failed to allocate memory\n", | 1985 | printk(KERN_WARNING "%s failed to allocate memory\n", |
| 1940 | __func__); | 1986 | __func__); |
| @@ -1947,7 +1993,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1947 | argv_free(helper_argv); | 1993 | argv_free(helper_argv); |
| 1948 | if (retval) { | 1994 | if (retval) { |
| 1949 | printk(KERN_INFO "Core dump to %s pipe failed\n", | 1995 | printk(KERN_INFO "Core dump to %s pipe failed\n", |
| 1950 | corename); | 1996 | cn.corename); |
| 1951 | goto close_fail; | 1997 | goto close_fail; |
| 1952 | } | 1998 | } |
| 1953 | } else { | 1999 | } else { |
| @@ -1956,7 +2002,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
| 1956 | if (cprm.limit < binfmt->min_coredump) | 2002 | if (cprm.limit < binfmt->min_coredump) |
| 1957 | goto fail_unlock; | 2003 | goto fail_unlock; |
| 1958 | 2004 | ||
| 1959 | cprm.file = filp_open(corename, | 2005 | cprm.file = filp_open(cn.corename, |
| 1960 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, | 2006 | O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, |
| 1961 | 0600); | 2007 | 0600); |
| 1962 | if (IS_ERR(cprm.file)) | 2008 | if (IS_ERR(cprm.file)) |
| @@ -1998,6 +2044,8 @@ fail_dropcount: | |||
| 1998 | if (ispipe) | 2044 | if (ispipe) |
| 1999 | atomic_dec(&core_dump_count); | 2045 | atomic_dec(&core_dump_count); |
| 2000 | fail_unlock: | 2046 | fail_unlock: |
| 2047 | kfree(cn.corename); | ||
| 2048 | fail_corename: | ||
| 2001 | coredump_finish(mm); | 2049 | coredump_finish(mm); |
| 2002 | revert_creds(old_cred); | 2050 | revert_creds(old_cred); |
| 2003 | fail_creds: | 2051 | fail_creds: |
| @@ -2005,3 +2053,43 @@ fail_creds: | |||
| 2005 | fail: | 2053 | fail: |
| 2006 | return; | 2054 | return; |
| 2007 | } | 2055 | } |
| 2056 | |||
| 2057 | /* | ||
| 2058 | * Core dumping helper functions. These are the only things you should | ||
| 2059 | * do on a core-file: use only these functions to write out all the | ||
| 2060 | * necessary info. | ||
| 2061 | */ | ||
| 2062 | int dump_write(struct file *file, const void *addr, int nr) | ||
| 2063 | { | ||
| 2064 | return access_ok(VERIFY_READ, addr, nr) && file->f_op->write(file, addr, nr, &file->f_pos) == nr; | ||
| 2065 | } | ||
| 2066 | EXPORT_SYMBOL(dump_write); | ||
| 2067 | |||
| 2068 | int dump_seek(struct file *file, loff_t off) | ||
| 2069 | { | ||
| 2070 | int ret = 1; | ||
| 2071 | |||
| 2072 | if (file->f_op->llseek && file->f_op->llseek != no_llseek) { | ||
| 2073 | if (file->f_op->llseek(file, off, SEEK_CUR) < 0) | ||
| 2074 | return 0; | ||
| 2075 | } else { | ||
| 2076 | char *buf = (char *)get_zeroed_page(GFP_KERNEL); | ||
| 2077 | |||
| 2078 | if (!buf) | ||
| 2079 | return 0; | ||
| 2080 | while (off > 0) { | ||
| 2081 | unsigned long n = off; | ||
| 2082 | |||
| 2083 | if (n > PAGE_SIZE) | ||
| 2084 | n = PAGE_SIZE; | ||
| 2085 | if (!dump_write(file, buf, n)) { | ||
| 2086 | ret = 0; | ||
| 2087 | break; | ||
| 2088 | } | ||
| 2089 | off -= n; | ||
| 2090 | } | ||
| 2091 | free_page((unsigned long)buf); | ||
| 2092 | } | ||
| 2093 | return ret; | ||
| 2094 | } | ||
| 2095 | EXPORT_SYMBOL(dump_seek); | ||
