Fix another bug introduced in r225641, which caused rctl to access certain
fields in 'struct proc' before they got initialized in do_fork(). MFC after: 3 days
This commit is contained in:
parent
ac6fafe6c2
commit
72a401d918
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=225940
@ -939,6 +939,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
|
||||
if (flags & RFPROCDESC)
|
||||
procdesc_finit(newproc->p_procdesc, fp_procdesc);
|
||||
#endif
|
||||
racct_proc_fork_done(newproc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -585,6 +585,24 @@ racct_proc_fork(struct proc *parent, struct proc *child)
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called at the end of fork1(), to handle rules that require the process
|
||||
* to be fully initialized.
|
||||
*/
|
||||
void
|
||||
racct_proc_fork_done(struct proc *child)
|
||||
{
|
||||
|
||||
#ifdef RCTL
|
||||
PROC_LOCK(child);
|
||||
mtx_lock(&racct_lock);
|
||||
rctl_enforce(child, RACCT_NPROC, 0);
|
||||
rctl_enforce(child, RACCT_NTHR, 0);
|
||||
mtx_unlock(&racct_lock);
|
||||
PROC_UNLOCK(child);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
racct_proc_exit(struct proc *p)
|
||||
{
|
||||
@ -809,6 +827,11 @@ racct_proc_fork(struct proc *parent, struct proc *child)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
racct_proc_fork_done(struct proc *child)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
racct_proc_exit(struct proc *p)
|
||||
{
|
||||
|
@ -312,6 +312,16 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
|
||||
if (link->rrl_exceeded != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the process state is not fully initialized yet,
|
||||
* we can't access most of the required fields, e.g.
|
||||
* p->p_comm. This happens when called from fork1().
|
||||
* Ignore this rule for now; it will be processed just
|
||||
* after fork, when called from racct_proc_fork_done().
|
||||
*/
|
||||
if (p->p_state != PRS_NORMAL)
|
||||
continue;
|
||||
|
||||
if (!ppsratecheck(&lasttime, &curtime, 10))
|
||||
continue;
|
||||
|
||||
@ -335,6 +345,9 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
|
||||
if (link->rrl_exceeded != 0)
|
||||
continue;
|
||||
|
||||
if (p->p_state != PRS_NORMAL)
|
||||
continue;
|
||||
|
||||
buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
|
||||
if (buf == NULL) {
|
||||
printf("rctl_enforce: out of memory\n");
|
||||
@ -357,22 +370,14 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
|
||||
if (link->rrl_exceeded != 0)
|
||||
continue;
|
||||
|
||||
if (p->p_state != PRS_NORMAL)
|
||||
continue;
|
||||
|
||||
KASSERT(rule->rr_action > 0 &&
|
||||
rule->rr_action <= RCTL_ACTION_SIGNAL_MAX,
|
||||
("rctl_enforce: unknown action %d",
|
||||
rule->rr_action));
|
||||
|
||||
/*
|
||||
* We're supposed to send a signal, but the process
|
||||
* is not fully initialized yet, probably because we
|
||||
* got called from fork1(). For now just deny the
|
||||
* allocation instead.
|
||||
*/
|
||||
if (p->p_state != PRS_NORMAL) {
|
||||
should_deny = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're using the fact that RCTL_ACTION_SIG* values
|
||||
* are equal to their counterparts from sys/signal.h.
|
||||
|
@ -137,6 +137,7 @@ void racct_create(struct racct **racctp);
|
||||
void racct_destroy(struct racct **racctp);
|
||||
|
||||
int racct_proc_fork(struct proc *parent, struct proc *child);
|
||||
void racct_proc_fork_done(struct proc *child);
|
||||
void racct_proc_exit(struct proc *p);
|
||||
|
||||
void racct_proc_ucred_changed(struct proc *p, struct ucred *oldcred,
|
||||
|
Loading…
Reference in New Issue
Block a user