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); | ||