1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-07 13:14:51 +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:
John Baldwin 2004-03-05 22:37:32 +00:00
parent 4eebf56527
commit 5ce2f67858
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=126670

View File

@ -217,14 +217,15 @@ fork1(td, flags, pages, procp)
return (EINVAL); return (EINVAL);
p1 = td->td_proc; p1 = td->td_proc;
mtx_lock(&Giant);
/* /*
* Here we don't create a new process, but we divorce * Here we don't create a new process, but we divorce
* certain parts of a process from itself. * certain parts of a process from itself.
*/ */
if ((flags & RFPROC) == 0) { if ((flags & RFPROC) == 0) {
mtx_lock(&Giant);
vm_forkproc(td, NULL, NULL, flags); vm_forkproc(td, NULL, NULL, flags);
mtx_unlock(&Giant);
/* /*
* Close all file descriptors. * Close all file descriptors.
@ -251,7 +252,6 @@ fork1(td, flags, pages, procp)
} else } else
FILEDESC_UNLOCK(p1->p_fd); FILEDESC_UNLOCK(p1->p_fd);
} }
mtx_unlock(&Giant);
*procp = NULL; *procp = NULL;
return (0); return (0);
} }
@ -270,6 +270,7 @@ fork1(td, flags, pages, procp)
* where they will try restart in the parent and will * where they will try restart in the parent and will
* be aborted in the child. * be aborted in the child.
*/ */
mtx_lock(&Giant);
PROC_LOCK(p1); PROC_LOCK(p1);
if (thread_single(SINGLE_NO_EXIT)) { if (thread_single(SINGLE_NO_EXIT)) {
/* Abort. Someone else is single threading before us. */ /* Abort. Someone else is single threading before us. */
@ -278,6 +279,7 @@ fork1(td, flags, pages, procp)
return (ERESTART); return (ERESTART);
} }
PROC_UNLOCK(p1); PROC_UNLOCK(p1);
mtx_unlock(&Giant);
/* /*
* All other activity in this process * All other activity in this process
* is now suspended at the user boundary, * is now suspended at the user boundary,
@ -291,6 +293,9 @@ fork1(td, flags, pages, procp)
mac_init_proc(newproc); mac_init_proc(newproc);
#endif #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 * Although process entries are dynamically created, we still keep
* a global limit on the maximum number we will create. Don't allow * 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)) { for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) {
PROC_LOCK(p2); PROC_LOCK(p2);
while (p2->p_pid == trypid || while (p2->p_pid == trypid ||
p2->p_pgrp->pg_id == trypid || (p2->p_pgrp != NULL &&
p2->p_session->s_sid == trypid) { (p2->p_pgrp->pg_id == trypid ||
(p2->p_session != NULL &&
p2->p_session->s_sid == trypid)))) {
trypid++; trypid++;
if (trypid >= pidchecked) { if (trypid >= pidchecked) {
PROC_UNLOCK(p2); PROC_UNLOCK(p2);
@ -375,12 +382,15 @@ fork1(td, flags, pages, procp)
} }
if (p2->p_pid > trypid && pidchecked > p2->p_pid) if (p2->p_pid > trypid && pidchecked > p2->p_pid)
pidchecked = p2->p_pid; pidchecked = p2->p_pid;
if (p2->p_pgrp->pg_id > trypid && if (p2->p_pgrp != NULL) {
pidchecked > p2->p_pgrp->pg_id) 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_pgrp->pg_id;
pidchecked > p2->p_session->s_sid) if (p2->p_session != NULL &&
pidchecked = p2->p_session->s_sid; p2->p_session->s_sid > trypid &&
pidchecked > p2->p_session->s_sid)
pidchecked = p2->p_session->s_sid;
}
PROC_UNLOCK(p2); PROC_UNLOCK(p2);
} }
if (!doingzomb) { if (!doingzomb) {
@ -389,6 +399,7 @@ fork1(td, flags, pages, procp)
goto again; goto again;
} }
} }
sx_sunlock(&proctree_lock);
/* /*
* RFHIGHPID does not mess with the lastpid counter during boot. * 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; p2->p_textvp = p1->p_textvp;
if (p2->p_textvp) if (p2->p_textvp)
VREF(p2->p_textvp); VREF(p2->p_textvp);
mtx_unlock(&Giant); /* XXX: for VREF() */
p2->p_fd = fd; p2->p_fd = fd;
p2->p_fdtol = fdtol; p2->p_fdtol = fdtol;
@ -656,6 +668,7 @@ fork1(td, flags, pages, procp)
* Finish creating the child process. It will return via a different * Finish creating the child process. It will return via a different
* execution path later. (ie: directly into user mode) * execution path later. (ie: directly into user mode)
*/ */
mtx_lock(&Giant);
vm_forkproc(td, p2, td2, flags); vm_forkproc(td, p2, td2, flags);
if (flags == (RFFDG | RFPROC)) { if (flags == (RFFDG | RFPROC)) {
@ -682,6 +695,7 @@ fork1(td, flags, pages, procp)
* What if they have an error? XXX * What if they have an error? XXX
*/ */
EVENTHANDLER_INVOKE(process_fork, p1, p2, flags); EVENTHANDLER_INVOKE(process_fork, p1, p2, flags);
mtx_unlock(&Giant);
/* /*
* Set the child start time and mark the process as being complete. * 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. * Return child proc pointer to parent.
*/ */
mtx_unlock(&Giant);
*procp = p2; *procp = p2;
return (0); return (0);
fail: fail:
sx_sunlock(&proctree_lock);
if (ppsratecheck(&lastfail, &curfail, 1)) if (ppsratecheck(&lastfail, &curfail, 1))
printf("maxproc limit exceeded by uid %i, please see tuning(7) and login.conf(5).\n", printf("maxproc limit exceeded by uid %i, please see tuning(7) and login.conf(5).\n",
uid); uid);
@ -753,7 +767,6 @@ fork1(td, flags, pages, procp)
PROC_UNLOCK(p1); PROC_UNLOCK(p1);
} }
tsleep(&forksleep, PUSER, "fork", hz / 2); tsleep(&forksleep, PUSER, "fork", hz / 2);
mtx_unlock(&Giant);
return (error); return (error);
} }
@ -811,7 +824,6 @@ fork_exit(callout, arg, frame)
PROC_LOCK(p); PROC_LOCK(p);
if (p->p_flag & P_KTHREAD) { if (p->p_flag & P_KTHREAD) {
PROC_UNLOCK(p); PROC_UNLOCK(p);
mtx_lock(&Giant);
printf("Kernel thread \"%s\" (pid %d) exited prematurely.\n", printf("Kernel thread \"%s\" (pid %d) exited prematurely.\n",
p->p_comm, p->p_pid); p->p_comm, p->p_pid);
kthread_exit(0); kthread_exit(0);