mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-06 13:09:50 +00:00
- Grab a share lock of the proctree lock while looking for a pid due to the
process group and session dereferences. Also, check that p_pgrp and p_sesssion are NULL before dereferencing them. - Push down Giant in fork1(). Requested by: peter
This commit is contained in:
parent
4eebf56527
commit
5ce2f67858
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=126670
@ -217,14 +217,15 @@ fork1(td, flags, pages, procp)
|
||||
return (EINVAL);
|
||||
|
||||
p1 = td->td_proc;
|
||||
mtx_lock(&Giant);
|
||||
|
||||
/*
|
||||
* Here we don't create a new process, but we divorce
|
||||
* certain parts of a process from itself.
|
||||
*/
|
||||
if ((flags & RFPROC) == 0) {
|
||||
mtx_lock(&Giant);
|
||||
vm_forkproc(td, NULL, NULL, flags);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
/*
|
||||
* Close all file descriptors.
|
||||
@ -251,7 +252,6 @@ fork1(td, flags, pages, procp)
|
||||
} else
|
||||
FILEDESC_UNLOCK(p1->p_fd);
|
||||
}
|
||||
mtx_unlock(&Giant);
|
||||
*procp = NULL;
|
||||
return (0);
|
||||
}
|
||||
@ -270,6 +270,7 @@ fork1(td, flags, pages, procp)
|
||||
* where they will try restart in the parent and will
|
||||
* be aborted in the child.
|
||||
*/
|
||||
mtx_lock(&Giant);
|
||||
PROC_LOCK(p1);
|
||||
if (thread_single(SINGLE_NO_EXIT)) {
|
||||
/* Abort. Someone else is single threading before us. */
|
||||
@ -278,6 +279,7 @@ fork1(td, flags, pages, procp)
|
||||
return (ERESTART);
|
||||
}
|
||||
PROC_UNLOCK(p1);
|
||||
mtx_unlock(&Giant);
|
||||
/*
|
||||
* All other activity in this process
|
||||
* is now suspended at the user boundary,
|
||||
@ -291,6 +293,9 @@ fork1(td, flags, pages, procp)
|
||||
mac_init_proc(newproc);
|
||||
#endif
|
||||
|
||||
/* We have to lock the process tree while we look for a pid. */
|
||||
sx_slock(&proctree_lock);
|
||||
|
||||
/*
|
||||
* Although process entries are dynamically created, we still keep
|
||||
* a global limit on the maximum number we will create. Don't allow
|
||||
@ -365,8 +370,10 @@ fork1(td, flags, pages, procp)
|
||||
for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) {
|
||||
PROC_LOCK(p2);
|
||||
while (p2->p_pid == trypid ||
|
||||
p2->p_pgrp->pg_id == trypid ||
|
||||
p2->p_session->s_sid == trypid) {
|
||||
(p2->p_pgrp != NULL &&
|
||||
(p2->p_pgrp->pg_id == trypid ||
|
||||
(p2->p_session != NULL &&
|
||||
p2->p_session->s_sid == trypid)))) {
|
||||
trypid++;
|
||||
if (trypid >= pidchecked) {
|
||||
PROC_UNLOCK(p2);
|
||||
@ -375,12 +382,15 @@ fork1(td, flags, pages, procp)
|
||||
}
|
||||
if (p2->p_pid > trypid && pidchecked > p2->p_pid)
|
||||
pidchecked = p2->p_pid;
|
||||
if (p2->p_pgrp->pg_id > trypid &&
|
||||
pidchecked > p2->p_pgrp->pg_id)
|
||||
pidchecked = p2->p_pgrp->pg_id;
|
||||
if (p2->p_session->s_sid > trypid &&
|
||||
pidchecked > p2->p_session->s_sid)
|
||||
pidchecked = p2->p_session->s_sid;
|
||||
if (p2->p_pgrp != NULL) {
|
||||
if (p2->p_pgrp->pg_id > trypid &&
|
||||
pidchecked > p2->p_pgrp->pg_id)
|
||||
pidchecked = p2->p_pgrp->pg_id;
|
||||
if (p2->p_session != NULL &&
|
||||
p2->p_session->s_sid > trypid &&
|
||||
pidchecked > p2->p_session->s_sid)
|
||||
pidchecked = p2->p_session->s_sid;
|
||||
}
|
||||
PROC_UNLOCK(p2);
|
||||
}
|
||||
if (!doingzomb) {
|
||||
@ -389,6 +399,7 @@ fork1(td, flags, pages, procp)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
sx_sunlock(&proctree_lock);
|
||||
|
||||
/*
|
||||
* RFHIGHPID does not mess with the lastpid counter during boot.
|
||||
@ -529,6 +540,7 @@ fork1(td, flags, pages, procp)
|
||||
p2->p_textvp = p1->p_textvp;
|
||||
if (p2->p_textvp)
|
||||
VREF(p2->p_textvp);
|
||||
mtx_unlock(&Giant); /* XXX: for VREF() */
|
||||
p2->p_fd = fd;
|
||||
p2->p_fdtol = fdtol;
|
||||
|
||||
@ -656,6 +668,7 @@ fork1(td, flags, pages, procp)
|
||||
* Finish creating the child process. It will return via a different
|
||||
* execution path later. (ie: directly into user mode)
|
||||
*/
|
||||
mtx_lock(&Giant);
|
||||
vm_forkproc(td, p2, td2, flags);
|
||||
|
||||
if (flags == (RFFDG | RFPROC)) {
|
||||
@ -682,6 +695,7 @@ fork1(td, flags, pages, procp)
|
||||
* What if they have an error? XXX
|
||||
*/
|
||||
EVENTHANDLER_INVOKE(process_fork, p1, p2, flags);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
/*
|
||||
* Set the child start time and mark the process as being complete.
|
||||
@ -735,10 +749,10 @@ fork1(td, flags, pages, procp)
|
||||
/*
|
||||
* Return child proc pointer to parent.
|
||||
*/
|
||||
mtx_unlock(&Giant);
|
||||
*procp = p2;
|
||||
return (0);
|
||||
fail:
|
||||
sx_sunlock(&proctree_lock);
|
||||
if (ppsratecheck(&lastfail, &curfail, 1))
|
||||
printf("maxproc limit exceeded by uid %i, please see tuning(7) and login.conf(5).\n",
|
||||
uid);
|
||||
@ -753,7 +767,6 @@ fork1(td, flags, pages, procp)
|
||||
PROC_UNLOCK(p1);
|
||||
}
|
||||
tsleep(&forksleep, PUSER, "fork", hz / 2);
|
||||
mtx_unlock(&Giant);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -811,7 +824,6 @@ fork_exit(callout, arg, frame)
|
||||
PROC_LOCK(p);
|
||||
if (p->p_flag & P_KTHREAD) {
|
||||
PROC_UNLOCK(p);
|
||||
mtx_lock(&Giant);
|
||||
printf("Kernel thread \"%s\" (pid %d) exited prematurely.\n",
|
||||
p->p_comm, p->p_pid);
|
||||
kthread_exit(0);
|
||||
|
Loading…
Reference in New Issue
Block a user