diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2026-06-05 20:21:59 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2026-06-08 20:14:20 +0000 |
| commit | a2cfe535771ded3ca8526bae405a5b61f71f1f33 (patch) | |
| tree | e43da13488f0b3ed43927ca9f0ddda51052d46e5 /sys/kern | |
| parent | 9f378397ee89044a4faec522916b50f0a164d62e (diff) | |
Diffstat (limited to 'sys/kern')
| -rw-r--r-- | sys/kern/kern_exec.c | 13 | ||||
| -rw-r--r-- | sys/kern/kern_exit.c | 57 | ||||
| -rw-r--r-- | sys/kern/kern_fork.c | 3 | ||||
| -rw-r--r-- | sys/kern/kern_ucoredump.c | 4 |
4 files changed, 63 insertions, 14 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 4066682cbcc5..8ea00543989e 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -341,11 +341,11 @@ post_execve(struct thread *td, int error, struct vmspace *oldvmspace) } /* - * kern_execve() has the astonishing property of not always returning to - * the caller. If sufficiently bad things happen during the call to - * do_execve(), it can end up calling exit1(); as a result, callers must - * avoid doing anything which they might need to undo (e.g., allocating - * memory). + * kern_execve() has the astonishing property of not always returning + * to the caller. If sufficiently bad things happen during the call + * to do_execve(), it can end up calling exit2(). Callers must avoid + * doing anything which they might need to undo (e.g., allocating + * memory), unless called from the ptrace(PT_SC_REMOTERQ) handler. */ int kern_execve(struct thread *td, struct image_args *args, struct mac *mac_p, @@ -1042,8 +1042,7 @@ exec_fail: if (error && imgp->vmspace_destroyed) { /* sorry, no more process anymore. exit gracefully */ exec_cleanup(td, oldvmspace); - exit1(td, 0, SIGABRT); - /* NOT REACHED */ + kern_exit(td, 0, SIGABRT); } #ifdef KTRACE diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 18ea3a7bd29d..63e46dcf46f7 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -204,9 +204,8 @@ exit_onexit(struct proc *p) int sys__exit(struct thread *td, struct _exit_args *uap) { - - exit1(td, uap->rval, 0); - __unreachable(); + kern_exit(td, uap->rval, 0); + return (0); } void @@ -216,6 +215,48 @@ proc_set_p2_wexit(struct proc *p) p->p_flag2 |= P2_WEXIT; } +static void +ast_async_exit(struct thread *td, int asts) +{ + struct proc *p; + + p = td->td_proc; + if ((p->p_flag & P_ASYNC_EXIT) != 0) + exit1(td, p->p_xexit, p->p_asig); +} + +/* + * The variation on exit1() intended to be used in the syscall + * handlers. Unlike exit1(), it might delay the current process exit + * to ast. This is needed e.g. when _exit(2) is executed due to the + * ptrace(PT_SC_REMOTERQ), which must do more work after the syscall + * handler call. + */ +void +kern_exit(struct thread *td, int rval, int signo) +{ + struct proc *p; + + KASSERT(rval == 0 || signo == 0, + ("kern_exit rv %d sig %d", rval, signo)); + + p = td->td_proc; + if ((td->td_dbgflags & TDB_SCREMOTEREQ) != 0) { + PROC_LOCK(p); + p->p_xexit = rval; + p->p_asig = signo; + p->p_flag |= P_ASYNC_EXIT; + ast_sched(td, TDA_ASYNC_EXIT); + PROC_UNLOCK(p); + return; + } + if ((p->p_flag & P_ASYNC_EXIT) != 0) { + rval = p->p_xexit; + signo = p->p_asig; + } + exit1(td, rval, signo); +} + /* * Exit: deallocate address space and other resources, change proc state to * zombie, and unlink proc from allproc and parent's lists. Save exit status @@ -231,6 +272,7 @@ exit1(struct thread *td, int rval, int signo) mtx_assert(&Giant, MA_NOTOWNED); KASSERT(rval == 0 || signo == 0, ("exit1 rv %d sig %d", rval, signo)); + MPASS((td->td_dbgflags & TDB_SCREMOTEREQ) == 0); TSPROCEXIT(td->td_proc->p_pid); p = td->td_proc; @@ -828,7 +870,7 @@ out: sbuf_delete(sb); PROC_LOCK(p); sigexit(td, sig); - /* NOTREACHED */ + return (0); } #ifdef COMPAT_43 @@ -1627,3 +1669,10 @@ proc_reparent(struct proc *child, struct proc *parent, bool set_oppid) if (set_oppid) child->p_oppid = parent->p_pid; } + +static void +initexit(void *dummy __unused) +{ + ast_register(TDA_ASYNC_EXIT, ASTR_ASTF_REQUIRED, 0, ast_async_exit); +} +SYSINIT(exit, SI_SUB_EXEC, SI_ORDER_ANY, initexit, NULL); diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 75f8413e5f36..2fb4d9d4274d 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -66,6 +66,7 @@ #include <sys/signalvar.h> #include <sys/sx.h> #include <sys/syscall.h> +#include <sys/syscallsubr.h> #include <sys/sysent.h> #include <sys/sysproto.h> #include <sys/vmmeter.h> @@ -1258,7 +1259,7 @@ fork_return(struct thread *td, struct trapframe *frame) * If the prison was killed mid-fork, die along with it. */ if (!prison_isalive(td->td_ucred->cr_prison)) - exit1(td, 0, SIGKILL); + kern_exit(td, 0, SIGKILL); #ifdef KTRACE if (KTRPOINT(td, KTR_SYSRET)) diff --git a/sys/kern/kern_ucoredump.c b/sys/kern/kern_ucoredump.c index d425596b5f24..e08490fbf7b1 100644 --- a/sys/kern/kern_ucoredump.c +++ b/sys/kern/kern_ucoredump.c @@ -46,6 +46,7 @@ #include <sys/racct.h> #include <sys/resourcevar.h> #include <sys/rmlock.h> +#include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/ucoredump.h> @@ -197,8 +198,7 @@ sigexit(struct thread *td, int sig) err != NULL ? err : ""); } else PROC_UNLOCK(p); - exit1(td, 0, sig); - /* NOTREACHED */ + kern_exit(td, 0, sig); } |
