*参照元 [#bb8f98fb] #backlinks *説明 [#ne4e0383] -パス: [[linux-2.6.33/]] -パス: [[linux-2.6.33/fs/exec.c]] -FIXME: これは何? --説明 **引数 [#v5ef7b8c] - -- **返り値 [#kf68d436] - -- **参考 [#x4cea0c9] *実装 [#pc820f02] void do_coredump(long signr, int exit_code, struct pt_regs *regs) { struct core_state core_state; - --[[linux-2.6.33/core_state]] char corename[CORENAME_MAX_SIZE + 1]; struct mm_struct *mm = current->mm; - --[[linux-2.6.33/mm_struct]] struct linux_binfmt * binfmt; - --[[linux-2.6.33/linux_binfmt]] struct inode * inode; - --[[linux-2.6.33/inode]] const struct cred *old_cred; struct cred *cred; - --[[linux-2.6.33/cred]] int retval = 0; int flag = 0; int ispipe = 0; char **helper_argv = NULL; int helper_argc = 0; int dump_count = 0; static atomic_t core_dump_count = ATOMIC_INIT(0); - --[[linux-2.6.33/atomic_t]] struct coredump_params cprm = { .signr = signr, .regs = regs, .limit = current->signal->rlim[RLIMIT_CORE].rlim_cur, }; - --[[linux-2.6.33/coredump_params]] audit_core_dumps(signr); - --[[linux-2.6.33/audit_core_dumps()]] binfmt = mm->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; cred = prepare_creds(); if (!cred) { retval = -ENOMEM; goto fail; } - --[[linux-2.6.33/prepare_creds()]] down_write(&mm->mmap_sem); - --[[linux-2.6.33/down_write()]] /* * If another thread got here first, or we are not dumpable, bail out. */ if (mm->core_state || !get_dumpable(mm)) { up_write(&mm->mmap_sem); put_cred(cred); goto fail; } - --[[linux-2.6.33/get_dumpable()]] - --[[linux-2.6.33/up_write()]] - --[[linux-2.6.33/put_cred()]] /* * We cannot trust fsuid as being the "true" uid of the * process nor do we know its entire history. We only know it * was tainted so we dump it as root in mode 2. */ if (get_dumpable(mm) == 2) { /* Setuid core dump mode */ flag = O_EXCL; /* Stop rewrite attacks */ cred->fsuid = 0; /* Dump root private */ } retval = coredump_wait(exit_code, &core_state); if (retval < 0) { put_cred(cred); goto fail; } - --[[linux-2.6.33/coredump_wait()]] old_cred = override_creds(cred); - --[[linux-2.6.33/override_creds()]] /* * Clear any false indication of pending signals that might * be seen by the filesystem code called to write the core file. */ clear_thread_flag(TIF_SIGPENDING); - --[[linux-2.6.33/clear_thread_flag()]] /* * lock_kernel() because format_corename() is controlled by sysctl, which * uses lock_kernel() */ lock_kernel(); - --[[linux-2.6.33/lock_kernel()]] ispipe = format_corename(corename, signr); - --[[linux-2.6.33/format_corename()]] unlock_kernel(); - --[[linux-2.6.33/unlock_kernel()]] if ((!ispipe) && (cprm.limit < binfmt->min_coredump)) goto fail_unlock; if (ispipe) { if (cprm.limit == 0) { /* * Normally core limits are irrelevant to pipes, since * we're not writing to the file system, but we use * cprm.limit of 0 here as a speacial value. Any * non-zero limit gets set to RLIM_INFINITY below, but * a limit of 0 skips the dump. This is a consistent * way to catch recursive crashes. We can still crash * if the core_pattern binary sets RLIM_CORE = !0 * but it runs as root, and can do lots of stupid things * Note that we use task_tgid_vnr here to grab the pid * of the process group leader. That way we get the * right pid if a thread in a multi-threaded * core_pattern process dies. */ printk(KERN_WARNING "Process %d(%s) has RLIMIT_CORE set to 0\n", task_tgid_vnr(current), current->comm); printk(KERN_WARNING "Aborting core\n"); goto fail_unlock; } - --[[linux-2.6.33/task_tgid_vnr()]] dump_count = atomic_inc_return(&core_dump_count); if (core_pipe_limit && (core_pipe_limit < dump_count)) { printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", task_tgid_vnr(current), current->comm); printk(KERN_WARNING "Skipping core dump\n"); goto fail_dropcount; } - --[[linux-2.6.33/atomic_inc_return()]] helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); if (!helper_argv) { printk(KERN_WARNING "%s failed to allocate memory\n", __func__); goto fail_dropcount; } - --[[linux-2.6.33/argv_split()]] cprm.limit = RLIM_INFINITY; /* SIGPIPE can happen, but it's just never processed */ if (call_usermodehelper_pipe(helper_argv[0], helper_argv, NULL, &cprm.file)) { printk(KERN_INFO "Core dump to %s pipe failed\n", corename); goto fail_dropcount; } - --[[linux-2.6.33/call_usermodehelper_pipe()]] } else cprm.file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600); - --[[linux-2.6.33/filp_open()]] if (IS_ERR(cprm.file)) goto fail_dropcount; inode = cprm.file->f_path.dentry->d_inode; if (inode->i_nlink > 1) goto close_fail; /* multiple links - don't dump */ if (!ispipe && d_unhashed(cprm.file->f_path.dentry)) goto close_fail; - --[[linux-2.6.33/IS_ERR()]] - --[[linux-2.6.33/d_unhashed()]] /* AK: actually i see no reason to not allow this for named pipes etc., but keep the previous behaviour for now. */ if (!ispipe && !S_ISREG(inode->i_mode)) goto close_fail; - --[[linux-2.6.33/S_ISREG()]] /* * Dont allow local users get cute and trick others to coredump * into their pre-created files: */ if (inode->i_uid != current_fsuid()) goto close_fail; if (!cprm.file->f_op) goto close_fail; if (!cprm.file->f_op->write) goto close_fail; if (!ispipe && do_truncate(cprm.file->f_path.dentry, 0, 0, cprm.file) != 0) goto close_fail; - --[[linux-2.6.33/current_fsuid()]] - --[[linux-2.6.33/do_truncate()]] retval = binfmt->core_dump(&cprm); - --[[linux-2.6.33/linux_binfmt]] if (retval) current->signal->group_exit_code |= 0x80; close_fail: if (ispipe && core_pipe_limit) wait_for_dump_helpers(cprm.file); - --[[linux-2.6.33/wait_for_dump_helpers()]] filp_close(cprm.file, NULL); - --[[linux-2.6.33/filp_close()]] fail_dropcount: if (dump_count) atomic_dec(&core_dump_count); - --[[linux-2.6.33/atomic_dec()]] fail_unlock: if (helper_argv) argv_free(helper_argv); - --[[linux-2.6.33/argv_free()]] revert_creds(old_cred); - --[[linux-2.6.33/revert_creds()]] put_cred(cred); - --[[linux-2.6.33/put_cred()]] coredump_finish(mm); - --[[linux-2.6.33/coredump_finish()]] fail: return; } *コメント [#j2c70d2e]