2005 lines · 49.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  linux/kernel/exit.c * *  Copyright (C) 1991, 1992  Linus Torvalds */ #include <linux/mm.h>#include <linux/slab.h>#include <linux/sched/autogroup.h>#include <linux/sched/mm.h>#include <linux/sched/stat.h>#include <linux/sched/task.h>#include <linux/sched/task_stack.h>#include <linux/sched/cputime.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/capability.h>#include <linux/completion.h>#include <linux/personality.h>#include <linux/tty.h>#include <linux/iocontext.h>#include <linux/key.h>#include <linux/cpu.h>#include <linux/acct.h>#include <linux/tsacct_kern.h>#include <linux/file.h>#include <linux/freezer.h>#include <linux/binfmts.h>#include <linux/nsproxy.h>#include <linux/pid_namespace.h>#include <linux/ptrace.h>#include <linux/profile.h>#include <linux/mount.h>#include <linux/proc_fs.h>#include <linux/kthread.h>#include <linux/mempolicy.h>#include <linux/taskstats_kern.h>#include <linux/delayacct.h>#include <linux/cgroup.h>#include <linux/syscalls.h>#include <linux/signal.h>#include <linux/posix-timers.h>#include <linux/cn_proc.h>#include <linux/mutex.h>#include <linux/futex.h>#include <linux/pipe_fs_i.h>#include <linux/audit.h> /* for audit_free() */#include <linux/resource.h>#include <linux/task_io_accounting_ops.h>#include <linux/blkdev.h>#include <linux/task_work.h>#include <linux/fs_struct.h>#include <linux/init_task.h>#include <linux/perf_event.h>#include <trace/events/sched.h>#include <linux/hw_breakpoint.h>#include <linux/oom.h>#include <linux/writeback.h>#include <linux/shm.h>#include <linux/kcov.h>#include <linux/kmsan.h>#include <linux/random.h>#include <linux/rcuwait.h>#include <linux/compat.h>#include <linux/io_uring.h>#include <linux/kprobes.h>#include <linux/rethook.h>#include <linux/sysfs.h>#include <linux/user_events.h>#include <linux/unwind_deferred.h>#include <linux/uaccess.h>#include <linux/pidfs.h> #include <uapi/linux/wait.h> #include <asm/unistd.h>#include <asm/mmu_context.h> #include "exit.h" /* * The default value should be high enough to not crash a system that randomly * crashes its kernel from time to time, but low enough to at least not permit * overflowing 32-bit refcounts or the ldsem writer count. */static unsigned int oops_limit = 10000; #ifdef CONFIG_SYSCTLstatic const struct ctl_table kern_exit_table[] = {	{		.procname       = "oops_limit",		.data           = &oops_limit,		.maxlen         = sizeof(oops_limit),		.mode           = 0644,		.proc_handler   = proc_douintvec,	},}; static __init int kernel_exit_sysctls_init(void){	register_sysctl_init("kernel", kern_exit_table);	return 0;}late_initcall(kernel_exit_sysctls_init);#endif static atomic_t oops_count = ATOMIC_INIT(0); #ifdef CONFIG_SYSFSstatic ssize_t oops_count_show(struct kobject *kobj, struct kobj_attribute *attr,			       char *page){	return sysfs_emit(page, "%d\n", atomic_read(&oops_count));} static struct kobj_attribute oops_count_attr = __ATTR_RO(oops_count); static __init int kernel_exit_sysfs_init(void){	sysfs_add_file_to_group(kernel_kobj, &oops_count_attr.attr, NULL);	return 0;}late_initcall(kernel_exit_sysfs_init);#endif /* * For things release_task() would like to do *after* tasklist_lock is released. */struct release_task_post {	struct pid *pids[PIDTYPE_MAX];}; static void __unhash_process(struct release_task_post *post, struct task_struct *p,			     bool group_dead){	struct pid *pid = task_pid(p); 	nr_threads--; 	detach_pid(post->pids, p, PIDTYPE_PID);	wake_up_all(&pid->wait_pidfd); 	if (group_dead) {		detach_pid(post->pids, p, PIDTYPE_TGID);		detach_pid(post->pids, p, PIDTYPE_PGID);		detach_pid(post->pids, p, PIDTYPE_SID); 		list_del_rcu(&p->tasks);		list_del_init(&p->sibling);		__this_cpu_dec(process_counts);	}	list_del_rcu(&p->thread_node);} /* * This function expects the tasklist_lock write-locked. */static void __exit_signal(struct release_task_post *post, struct task_struct *tsk){	struct signal_struct *sig = tsk->signal;	bool group_dead = thread_group_leader(tsk);	struct sighand_struct *sighand;	struct tty_struct *tty;	u64 utime, stime; 	sighand = rcu_dereference_check(tsk->sighand,					lockdep_tasklist_lock_is_held());	spin_lock(&sighand->siglock); #ifdef CONFIG_POSIX_TIMERS	posix_cpu_timers_exit(tsk);	if (group_dead)		posix_cpu_timers_exit_group(tsk);#endif 	if (group_dead) {		tty = sig->tty;		sig->tty = NULL;	} else {		/*		 * If there is any task waiting for the group exit		 * then notify it:		 */		if (sig->notify_count > 0 && !--sig->notify_count)			wake_up_process(sig->group_exec_task); 		if (tsk == sig->curr_target)			sig->curr_target = next_thread(tsk);	} 	/*	 * Accumulate here the counters for all threads as they die. We could	 * skip the group leader because it is the last user of signal_struct,	 * but we want to avoid the race with thread_group_cputime() which can	 * see the empty ->thread_head list.	 */	task_cputime(tsk, &utime, &stime);	write_seqlock(&sig->stats_lock);	sig->utime += utime;	sig->stime += stime;	sig->gtime += task_gtime(tsk);	sig->min_flt += tsk->min_flt;	sig->maj_flt += tsk->maj_flt;	sig->nvcsw += tsk->nvcsw;	sig->nivcsw += tsk->nivcsw;	sig->inblock += task_io_get_inblock(tsk);	sig->oublock += task_io_get_oublock(tsk);	task_io_accounting_add(&sig->ioac, &tsk->ioac);	sig->sum_sched_runtime += tsk->se.sum_exec_runtime;	sig->nr_threads--;	__unhash_process(post, tsk, group_dead);	write_sequnlock(&sig->stats_lock); 	tsk->sighand = NULL;	spin_unlock(&sighand->siglock); 	__cleanup_sighand(sighand);	if (group_dead)		tty_kref_put(tty);} static void delayed_put_task_struct(struct rcu_head *rhp){	struct task_struct *tsk = container_of(rhp, struct task_struct, rcu); 	kprobe_flush_task(tsk);	rethook_flush_task(tsk);	perf_event_delayed_put(tsk);	trace_sched_process_free(tsk);	put_task_struct(tsk);} void put_task_struct_rcu_user(struct task_struct *task){	if (refcount_dec_and_test(&task->rcu_users))		call_rcu(&task->rcu, delayed_put_task_struct);} void __weak release_thread(struct task_struct *dead_task){} void release_task(struct task_struct *p){	struct release_task_post post;	struct task_struct *leader;	struct pid *thread_pid;	int zap_leader;repeat:	memset(&post, 0, sizeof(post)); 	/* don't need to get the RCU readlock here - the process is dead and	 * can't be modifying its own credentials. */	dec_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1); 	pidfs_exit(p);	cgroup_task_release(p); 	/* Retrieve @thread_pid before __unhash_process() may set it to NULL. */	thread_pid = task_pid(p); 	write_lock_irq(&tasklist_lock);	ptrace_release_task(p);	__exit_signal(&post, p); 	/*	 * If we are the last non-leader member of the thread	 * group, and the leader is zombie, then notify the	 * group leader's parent process. (if it wants notification.)	 */	zap_leader = 0;	leader = p->group_leader;	if (leader != p && thread_group_empty(leader)			&& leader->exit_state == EXIT_ZOMBIE) {		/* for pidfs_exit() and do_notify_parent() */		if (leader->signal->flags & SIGNAL_GROUP_EXIT)			leader->exit_code = leader->signal->group_exit_code;		/*		 * If we were the last child thread and the leader has		 * exited already, and the leader's parent ignores SIGCHLD,		 * then we are the one who should release the leader.		 */		zap_leader = do_notify_parent(leader, leader->exit_signal);		if (zap_leader)			leader->exit_state = EXIT_DEAD;	} 	write_unlock_irq(&tasklist_lock);	/* @thread_pid can't go away until free_pids() below */	proc_flush_pid(thread_pid);	exit_cred_namespaces(p);	add_device_randomness(&p->se.sum_exec_runtime,			      sizeof(p->se.sum_exec_runtime));	free_pids(post.pids);	release_thread(p);	/*	 * This task was already removed from the process/thread/pid lists	 * and lock_task_sighand(p) can't succeed. Nobody else can touch	 * ->pending or, if group dead, signal->shared_pending. We can call	 * flush_sigqueue() lockless.	 */	flush_sigqueue(&p->pending);	if (thread_group_leader(p))		flush_sigqueue(&p->signal->shared_pending); 	put_task_struct_rcu_user(p); 	p = leader;	if (unlikely(zap_leader))		goto repeat;} int rcuwait_wake_up(struct rcuwait *w){	int ret = 0;	struct task_struct *task; 	rcu_read_lock(); 	/*	 * Order condition vs @task, such that everything prior to the load	 * of @task is visible. This is the condition as to why the user called	 * rcuwait_wake() in the first place. Pairs with set_current_state()	 * barrier (A) in rcuwait_wait_event().	 *	 *    WAIT                WAKE	 *    [S] tsk = current	  [S] cond = true	 *        MB (A)	      MB (B)	 *    [L] cond		  [L] tsk	 */	smp_mb(); /* (B) */ 	task = rcu_dereference(w->task);	if (task)		ret = wake_up_process(task);	rcu_read_unlock(); 	return ret;}EXPORT_SYMBOL_GPL(rcuwait_wake_up); /* * Determine if a process group is "orphaned", according to the POSIX * definition in 2.2.2.52.  Orphaned process groups are not to be affected * by terminal-generated stop signals.  Newly orphaned process groups are * to receive a SIGHUP and a SIGCONT. * * "I ask you, have you ever known what it is to be an orphan?" */static int will_become_orphaned_pgrp(struct pid *pgrp,					struct task_struct *ignored_task){	struct task_struct *p; 	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {		if ((p == ignored_task) ||		    (p->exit_state && thread_group_empty(p)) ||		    is_global_init(p->real_parent))			continue; 		if (task_pgrp(p->real_parent) != pgrp &&		    task_session(p->real_parent) == task_session(p))			return 0;	} while_each_pid_task(pgrp, PIDTYPE_PGID, p); 	return 1;} int is_current_pgrp_orphaned(void){	int retval; 	read_lock(&tasklist_lock);	retval = will_become_orphaned_pgrp(task_pgrp(current), NULL);	read_unlock(&tasklist_lock); 	return retval;} static bool has_stopped_jobs(struct pid *pgrp){	struct task_struct *p; 	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {		if (p->signal->flags & SIGNAL_STOP_STOPPED)			return true;	} while_each_pid_task(pgrp, PIDTYPE_PGID, p); 	return false;} /* * Check to see if any process groups have become orphaned as * a result of our exiting, and if they have any stopped jobs, * send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) */static voidkill_orphaned_pgrp(struct task_struct *tsk, struct task_struct *parent){	struct pid *pgrp = task_pgrp(tsk);	struct task_struct *ignored_task = tsk; 	if (!parent)		/* exit: our father is in a different pgrp than		 * we are and we were the only connection outside.		 */		parent = tsk->real_parent;	else		/* reparent: our child is in a different pgrp than		 * we are, and it was the only connection outside.		 */		ignored_task = NULL; 	if (task_pgrp(parent) != pgrp &&	    task_session(parent) == task_session(tsk) &&	    will_become_orphaned_pgrp(pgrp, ignored_task) &&	    has_stopped_jobs(pgrp)) {		__kill_pgrp_info(SIGHUP, SEND_SIG_PRIV, pgrp);		__kill_pgrp_info(SIGCONT, SEND_SIG_PRIV, pgrp);	}} static void coredump_task_exit(struct task_struct *tsk,			       struct core_state *core_state){	struct core_thread self; 	self.task = tsk;	if (self.task->flags & PF_SIGNALED)		self.next = xchg(&core_state->dumper.next, &self);	else		self.task = NULL;	/*	 * Implies mb(), the result of xchg() must be visible	 * to core_state->dumper.	 */	if (atomic_dec_and_test(&core_state->nr_threads))		complete(&core_state->startup); 	for (;;) {		set_current_state(TASK_IDLE|TASK_FREEZABLE);		if (!self.task) /* see coredump_finish() */			break;		schedule();	}	__set_current_state(TASK_RUNNING);} #ifdef CONFIG_MEMCG/* drops tasklist_lock if succeeds */static bool __try_to_set_owner(struct task_struct *tsk, struct mm_struct *mm){	bool ret = false; 	task_lock(tsk);	if (likely(tsk->mm == mm)) {		/* tsk can't pass exit_mm/exec_mmap and exit */		read_unlock(&tasklist_lock);		WRITE_ONCE(mm->owner, tsk);		lru_gen_migrate_mm(mm);		ret = true;	}	task_unlock(tsk);	return ret;} static bool try_to_set_owner(struct task_struct *g, struct mm_struct *mm){	struct task_struct *t; 	for_each_thread(g, t) {		struct mm_struct *t_mm = READ_ONCE(t->mm);		if (t_mm == mm) {			if (__try_to_set_owner(t, mm))				return true;		} else if (t_mm)			break;	} 	return false;} /* * A task is exiting.   If it owned this mm, find a new owner for the mm. */void mm_update_next_owner(struct mm_struct *mm){	struct task_struct *g, *p = current; 	/*	 * If the exiting or execing task is not the owner, it's	 * someone else's problem.	 */	if (mm->owner != p)		return;	/*	 * The current owner is exiting/execing and there are no other	 * candidates.  Do not leave the mm pointing to a possibly	 * freed task structure.

Lines 1–500 of 2005.