diff options
author | trasz <trasz@FreeBSD.org> | 2011-10-03 16:23:20 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2011-10-03 16:23:20 +0000 |
commit | 82df9bbbc475882013138f9a5205f8a1e3c88070 (patch) | |
tree | 525c99c9f4e41ee0a50aad6f301ce45842ec7446 /sys/kern | |
parent | 138a535460213399389b2c4da12e1d65b6061ef3 (diff) | |
download | FreeBSD-src-82df9bbbc475882013138f9a5205f8a1e3c88070.zip FreeBSD-src-82df9bbbc475882013138f9a5205f8a1e3c88070.tar.gz |
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
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_fork.c | 1 | ||||
-rw-r--r-- | sys/kern/kern_racct.c | 23 | ||||
-rw-r--r-- | sys/kern/kern_rctl.c | 27 |
3 files changed, 40 insertions, 11 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index a3634b7..072908f 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -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); } diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index 525866c..8414cda 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -585,6 +585,24 @@ out: 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) { @@ -810,6 +828,11 @@ racct_proc_fork(struct proc *parent, struct proc *child) } void +racct_proc_fork_done(struct proc *child) +{ +} + +void racct_proc_exit(struct proc *p) { } diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c index d5bd010..ad31456 100644 --- a/sys/kern/kern_rctl.c +++ b/sys/kern/kern_rctl.c @@ -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,23 +370,15 @@ 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. */ |