proc: add tree ref count

Owning the reference prevents reuse of the struct proc.

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D57492
This commit is contained in:
Konstantin Belousov
2026-06-06 21:02:29 +03:00
parent a248c5545f
commit 85a65e3930
4 changed files with 11 additions and 2 deletions
+1 -1
View File
@@ -1107,7 +1107,7 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
KASSERT(FIRST_THREAD_IN_PROC(p), KASSERT(FIRST_THREAD_IN_PROC(p),
("proc_reap: no residual thread!")); ("proc_reap: no residual thread!"));
uma_zfree(proc_zone, p); PROC_TREE_UNREF(p);
atomic_add_int(&nprocs, -1); atomic_add_int(&nprocs, -1);
} }
+2 -1
View File
@@ -1051,6 +1051,7 @@ fork1(struct thread *td, struct fork_req *fr)
pages = kstack_pages; pages = kstack_pages;
/* Allocate new proc. */ /* Allocate new proc. */
newproc = uma_zalloc(proc_zone, M_WAITOK); newproc = uma_zalloc(proc_zone, M_WAITOK);
PROC_TREE_REF(newproc);
td2 = FIRST_THREAD_IN_PROC(newproc); td2 = FIRST_THREAD_IN_PROC(newproc);
if (td2 == NULL) { if (td2 == NULL) {
td2 = thread_alloc(pages); td2 = thread_alloc(pages);
@@ -1131,7 +1132,7 @@ fork1(struct thread *td, struct fork_req *fr)
fail2: fail2:
if (vm2 != NULL) if (vm2 != NULL)
vmspace_free(vm2); vmspace_free(vm2);
uma_zfree(proc_zone, newproc); PROC_TREE_UNREF(newproc);
if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) { if ((flags & RFPROCDESC) != 0 && fp_procdesc != NULL) {
fdclose(td, fp_procdesc, *fr->fr_pd_fd); fdclose(td, fp_procdesc, *fr->fr_pd_fd);
fdrop(fp_procdesc, td); fdrop(fp_procdesc, td);
+1
View File
@@ -279,6 +279,7 @@ proc_init(void *mem, int size, int flags)
p->p_pgrp = NULL; p->p_pgrp = NULL;
TAILQ_INIT(&p->p_kqtim_stop); TAILQ_INIT(&p->p_kqtim_stop);
STAILQ_INIT(&p->p_ktr); STAILQ_INIT(&p->p_ktr);
refcount_init(&p->p_tree_refcnt, 0);
return (0); return (0);
} }
+7
View File
@@ -779,6 +779,7 @@ struct proc {
TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */ TAILQ_HEAD(, kq_timer_cb_data) p_kqtim_stop; /* (c) */
LIST_ENTRY(proc) p_jaillist; /* (d) Jail process linkage. */ LIST_ENTRY(proc) p_jaillist; /* (d) Jail process linkage. */
u_int p_asig; /* (c) ASYNCEXIT pending signal. */ u_int p_asig; /* (c) ASYNCEXIT pending signal. */
u_int p_tree_refcnt; /* (e) proctree refcount */
}; };
#define p_session p_pgrp->pg_session #define p_session p_pgrp->pg_session
@@ -804,6 +805,12 @@ struct proc {
#define PROC_PROFUNLOCK(p) mtx_unlock_spin(&(p)->p_profmtx) #define PROC_PROFUNLOCK(p) mtx_unlock_spin(&(p)->p_profmtx)
#define PROC_PROFLOCK_ASSERT(p, type) mtx_assert(&(p)->p_profmtx, (type)) #define PROC_PROFLOCK_ASSERT(p, type) mtx_assert(&(p)->p_profmtx, (type))
#define PROC_TREE_REF(p) refcount_acquire(&(p)->p_tree_refcnt)
#define PROC_TREE_UNREF(p) do { \
if (refcount_release(&(p)->p_tree_refcnt)) \
uma_zfree(proc_zone, p); \
} while (0)
/* These flags are kept in p_flag. */ /* These flags are kept in p_flag. */
#define P_ADVLOCK 0x00000001 /* Process may hold a POSIX advisory #define P_ADVLOCK 0x00000001 /* Process may hold a POSIX advisory
lock. */ lock. */