Fix panic in procdesc that can be triggered in the following scenario:
1. Process A pdfork(2)s process B. 2. Process A passes process descriptor of B to unrelated process C. 3. Hit CTRL+C to terminate process A. Process B is also terminated with SIGINT. 4. init(8) collects status of process B. 5. Process C closes process descriptor associated with process B. When we have such order of events, init(8), by collecting status of process B, will call procdesc_reap(). This function sets pd_proc to NULL. Now when process C calls close on this process descriptor, procdesc_close() is called. Unfortunately procdesc_close() assumes that pd_proc points at a valid proc structure, but it was set to NULL earlier, so the kernel panics. The patch also adds setting 'p->p_procdesc' to NULL in procdesc_reap(), which I think should be done. MFC after: 1 week
This commit is contained in:
parent
98e695d7fd
commit
707641ec28
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=239989
@ -333,6 +333,7 @@ procdesc_reap(struct proc *p)
|
||||
|
||||
pd = p->p_procdesc;
|
||||
pd->pd_proc = NULL;
|
||||
p->p_procdesc = NULL;
|
||||
procdesc_free(pd);
|
||||
}
|
||||
|
||||
@ -358,14 +359,20 @@ procdesc_close(struct file *fp, struct thread *td)
|
||||
pd->pd_flags |= PDF_CLOSED;
|
||||
PROCDESC_UNLOCK(pd);
|
||||
p = pd->pd_proc;
|
||||
PROC_LOCK(p);
|
||||
if (p->p_state == PRS_ZOMBIE) {
|
||||
if (p == NULL) {
|
||||
/*
|
||||
* This is the case where process' exit status was already
|
||||
* collected and procdesc_reap() was already called.
|
||||
*/
|
||||
sx_xunlock(&proctree_lock);
|
||||
} else if (p->p_state == PRS_ZOMBIE) {
|
||||
/*
|
||||
* If the process is already dead and just awaiting reaping,
|
||||
* do that now. This will release the process's reference to
|
||||
* the process descriptor when it calls back into
|
||||
* procdesc_reap().
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
PROC_SLOCK(p);
|
||||
proc_reap(curthread, p, NULL, 0, NULL);
|
||||
} else {
|
||||
@ -376,6 +383,7 @@ procdesc_close(struct file *fp, struct thread *td)
|
||||
* process from its descriptor so that its exit status will
|
||||
* be reported normally.
|
||||
*/
|
||||
PROC_LOCK(p);
|
||||
pd->pd_proc = NULL;
|
||||
p->p_procdesc = NULL;
|
||||
procdesc_free(pd);
|
||||
|
Loading…
Reference in New Issue
Block a user