leader->group_leader = tsk;
tsk->exit_signal = SIGCHLD;
+ leader->exit_signal = -1;
BUG_ON(leader->exit_state != EXIT_ZOMBIE);
leader->exit_state = EXIT_DEAD;
+
+ /*
+ * We are going to release_task()->ptrace_unlink() silently,
+ * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
+ * the tracer wont't block again waiting for this thread.
+ */
+ if (unlikely(leader->ptrace))
+ __wake_up_parent(leader, leader->parent);
write_unlock_irq(&tasklist_lock);
release_task(leader);
}
EXPORT_SYMBOL(flush_old_exec);
+void would_dump(struct linux_binprm *bprm, struct file *file)
+{
+ if (inode_permission(file->f_path.dentry->d_inode, MAY_READ) < 0)
+ bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+}
+EXPORT_SYMBOL(would_dump);
+
void setup_new_exec(struct linux_binprm * bprm)
{
int i, ch;
if (bprm->cred->uid != current_euid() ||
bprm->cred->gid != current_egid()) {
current->pdeath_signal = 0;
- } else if (file_permission(bprm->file, MAY_READ) ||
- bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) {
- set_dumpable(current->mm, suid_dumpable);
+ } else {
+ would_dump(bprm, bprm->file);
+ if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
+ set_dumpable(current->mm, suid_dumpable);
}
/*
unsigned n_fs;
int res = 0;
- bprm->unsafe = tracehook_unsafe_exec(p);
+ if (p->ptrace) {
+ if (p->ptrace & PT_PTRACE_CAP)
+ bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
+ else
+ bprm->unsafe |= LSM_UNSAFE_PTRACE;
+ }
n_fs = 1;
spin_lock(&p->fs->lock);
unsigned int depth = bprm->recursion_depth;
int try,retval;
struct linux_binfmt *fmt;
+ pid_t old_pid;
retval = security_bprm_check(bprm);
if (retval)
if (retval)
return retval;
+ /* Need to fetch pid before load_binary changes it */
+ rcu_read_lock();
+ old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
+ rcu_read_unlock();
+
retval = -ENOENT;
for (try=0; try<2; try++) {
read_lock(&binfmt_lock);
bprm->recursion_depth = depth;
if (retval >= 0) {
if (depth == 0)
- tracehook_report_exec(fmt, bprm, regs);
+ ptrace_event(PTRACE_EVENT_EXEC,
+ old_pid);
put_binfmt(fmt);
allow_write_access(bprm->file);
if (bprm->file)
return ret;
}
+static void cn_escape(char *str)
+{
+ for (; *str; str++)
+ if (*str == '/')
+ *str = '!';
+}
+
static int cn_print_exe_file(struct core_name *cn)
{
struct file *exe_file;
- char *pathbuf, *path, *p;
+ char *pathbuf, *path;
int ret;
exe_file = get_mm_exe_file(current->mm);
- if (!exe_file)
- return cn_printf(cn, "(unknown)");
+ if (!exe_file) {
+ char *commstart = cn->corename + cn->used;
+ ret = cn_printf(cn, "%s (path unknown)", current->comm);
+ cn_escape(commstart);
+ return ret;
+ }
pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
if (!pathbuf) {
goto free_buf;
}
- for (p = path; *p; p++)
- if (*p == '/')
- *p = '!';
+ cn_escape(path);
ret = cn_printf(cn, "%s", path);
break;
}
/* hostname */
- case 'h':
+ case 'h': {
+ char *namestart = cn->corename + cn->used;
down_read(&uts_sem);
err = cn_printf(cn, "%s",
utsname()->nodename);
up_read(&uts_sem);
+ cn_escape(namestart);
break;
+ }
/* executable */
- case 'e':
+ case 'e': {
+ char *commstart = cn->corename + cn->used;
err = cn_printf(cn, "%s", current->comm);
+ cn_escape(commstart);
break;
+ }
case 'E':
err = cn_print_exe_file(cn);
break;
t = start;
do {
- task_clear_group_stop_pending(t);
+ task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
if (t != current && t->mm) {
sigaddset(&t->pending.signal, SIGKILL);
signal_wake_up(t, 1);
ispipe = format_corename(&cn, signr);
- if (ispipe == -ENOMEM) {
- printk(KERN_WARNING "format_corename failed\n");
- printk(KERN_WARNING "Aborting core\n");
- goto fail_corename;
- }
-
if (ispipe) {
int dump_count;
char **helper_argv;
+ if (ispipe < 0) {
+ printk(KERN_WARNING "format_corename failed\n");
+ printk(KERN_WARNING "Aborting core\n");
+ goto fail_corename;
+ }
+
if (cprm.limit == 1) {
/*
* Normally core limits are irrelevant to pipes, since