diff options
author | trasz <trasz@FreeBSD.org> | 2011-05-03 07:32:58 +0000 |
---|---|---|
committer | trasz <trasz@FreeBSD.org> | 2011-05-03 07:32:58 +0000 |
commit | 752ffacc695ca593f052934a2881be57dec92419 (patch) | |
tree | 83f996220eb5127d50beee996ac337678876fccc /sys/kern/kern_rctl.c | |
parent | a857ffe8345f7868b2fb1f9f4b0606558ecba6ca (diff) | |
download | FreeBSD-src-752ffacc695ca593f052934a2881be57dec92419.zip FreeBSD-src-752ffacc695ca593f052934a2881be57dec92419.tar.gz |
Change the way rctl interfaces with jails by introducing prison_racct
structure, which acts as a proxy between them. This makes jail rules
persistent, i.e. they can be added before jail gets created, and they
don't disappear when the jail gets destroyed.
Diffstat (limited to 'sys/kern/kern_rctl.c')
-rw-r--r-- | sys/kern/kern_rctl.c | 95 |
1 files changed, 37 insertions, 58 deletions
diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c index 88a971c..2d43bdc 100644 --- a/sys/kern/kern_rctl.c +++ b/sys/kern/kern_rctl.c @@ -241,7 +241,8 @@ rctl_available_resource(const struct proc *p, const struct rctl_rule *rule) break; case RCTL_SUBJECT_TYPE_JAIL: available = rule->rr_amount - - cred->cr_prison->pr_racct->r_resources[resource]; + cred->cr_prison->pr_prison_racct->prr_racct-> + r_resources[resource]; break; default: panic("rctl_compute_available: unknown per %d", @@ -327,7 +328,7 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount) printf("rctl: rule \"%s\" matched by pid %d " "(%s), uid %d, jail %s\n", sbuf_data(&sb), p->p_pid, p->p_comm, p->p_ucred->cr_uid, - p->p_ucred->cr_prison->pr_name); + p->p_ucred->cr_prison->pr_prison_racct->prr_name); sbuf_delete(&sb); free(buf, M_RCTL); link->rrl_exceeded = 1; @@ -346,7 +347,7 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount) rctl_rule_to_sbuf(&sb, rule); sbuf_printf(&sb, " pid=%d ruid=%d jail=%s", p->p_pid, p->p_ucred->cr_ruid, - p->p_ucred->cr_prison->pr_name); + p->p_ucred->cr_prison->pr_prison_racct->prr_name); sbuf_finish(&sb); devctl_notify_f("RCTL", "rule", "matched", sbuf_data(&sb), M_NOWAIT); @@ -481,9 +482,9 @@ rctl_rule_matches(const struct rctl_rule *rule, const struct rctl_rule *filter) return (0); break; case RCTL_SUBJECT_TYPE_JAIL: - if (filter->rr_subject.rs_prison != NULL && - rule->rr_subject.rs_prison != - filter->rr_subject.rs_prison) + if (filter->rr_subject.rs_prison_racct != NULL && + rule->rr_subject.rs_prison_racct != + filter->rr_subject.rs_prison_racct) return (0); break; default: @@ -635,7 +636,10 @@ rctl_rule_acquire_subject(struct rctl_rule *rule) switch (rule->rr_subject_type) { case RCTL_SUBJECT_TYPE_UNDEFINED: case RCTL_SUBJECT_TYPE_PROCESS: + break; case RCTL_SUBJECT_TYPE_JAIL: + if (rule->rr_subject.rs_prison_racct != NULL) + prison_racct_hold(rule->rr_subject.rs_prison_racct); break; case RCTL_SUBJECT_TYPE_USER: if (rule->rr_subject.rs_uip != NULL) @@ -658,7 +662,10 @@ rctl_rule_release_subject(struct rctl_rule *rule) switch (rule->rr_subject_type) { case RCTL_SUBJECT_TYPE_UNDEFINED: case RCTL_SUBJECT_TYPE_PROCESS: + break; case RCTL_SUBJECT_TYPE_JAIL: + if (rule->rr_subject.rs_prison_racct != NULL) + prison_racct_free(rule->rr_subject.rs_prison_racct); break; case RCTL_SUBJECT_TYPE_USER: if (rule->rr_subject.rs_uip != NULL) @@ -686,7 +693,7 @@ rctl_rule_alloc(int flags) rule->rr_subject.rs_proc = NULL; rule->rr_subject.rs_uip = NULL; rule->rr_subject.rs_loginclass = NULL; - rule->rr_subject.rs_prison = NULL; + rule->rr_subject.rs_prison_racct = NULL; rule->rr_per = RCTL_SUBJECT_TYPE_UNDEFINED; rule->rr_resource = RACCT_UNDEFINED; rule->rr_action = RCTL_ACTION_UNDEFINED; @@ -708,7 +715,7 @@ rctl_rule_duplicate(const struct rctl_rule *rule, int flags) copy->rr_subject.rs_proc = rule->rr_subject.rs_proc; copy->rr_subject.rs_uip = rule->rr_subject.rs_uip; copy->rr_subject.rs_loginclass = rule->rr_subject.rs_loginclass; - copy->rr_subject.rs_prison = rule->rr_subject.rs_prison; + copy->rr_subject.rs_prison_racct = rule->rr_subject.rs_prison_racct; copy->rr_per = rule->rr_per; copy->rr_resource = rule->rr_resource; copy->rr_action = rule->rr_action; @@ -784,7 +791,7 @@ rctl_rule_fully_specified(const struct rctl_rule *rule) return (0); break; case RCTL_SUBJECT_TYPE_JAIL: - if (rule->rr_subject.rs_prison == NULL) + if (rule->rr_subject.rs_prison_racct == NULL) return (0); break; default: @@ -833,7 +840,7 @@ rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep) rule->rr_subject.rs_proc = NULL; rule->rr_subject.rs_uip = NULL; rule->rr_subject.rs_loginclass = NULL; - rule->rr_subject.rs_prison = NULL; + rule->rr_subject.rs_prison_racct = NULL; } else { switch (rule->rr_subject_type) { case RCTL_SUBJECT_TYPE_UNDEFINED: @@ -866,23 +873,12 @@ rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep) } break; case RCTL_SUBJECT_TYPE_JAIL: - rule->rr_subject.rs_prison = - prison_find_name(&prison0, subject_idstr); - if (rule->rr_subject.rs_prison == NULL) { - /* - * No jail with that name; try with the JID. - */ - error = str2id(subject_idstr, &id); - if (error != 0) - goto out; - rule->rr_subject.rs_prison = prison_find(id); - if (rule->rr_subject.rs_prison == NULL) { - error = ESRCH; - goto out; - } + rule->rr_subject.rs_prison_racct = + prison_racct_find(subject_idstr); + if (rule->rr_subject.rs_prison_racct == NULL) { + error = ENAMETOOLONG; + goto out; } - /* prison_find() returns with mutex held. */ - mtx_unlock(&rule->rr_subject.rs_prison->pr_mtx); break; default: panic("rctl_string_to_rule: unknown subject type %d", @@ -944,6 +940,7 @@ rctl_rule_add(struct rctl_rule *rule) struct ucred *cred; struct uidinfo *uip; struct prison *pr; + struct prison_racct *prr; struct loginclass *lc; struct rctl_rule *rule2; int match; @@ -1008,9 +1005,9 @@ rctl_rule_add(struct rctl_rule *rule) break; case RCTL_SUBJECT_TYPE_JAIL: - pr = rule->rr_subject.rs_prison; - KASSERT(pr != NULL, ("rctl_rule_add: NULL pr")); - rctl_racct_add_rule(pr->pr_racct, rule); + prr = rule->rr_subject.rs_prison_racct; + KASSERT(prr != NULL, ("rctl_rule_add: NULL pr")); + rctl_racct_add_rule(prr->prr_racct, rule); break; default: @@ -1040,7 +1037,7 @@ rctl_rule_add(struct rctl_rule *rule) case RCTL_SUBJECT_TYPE_JAIL: match = 0; for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) { - if (pr == rule->rr_subject.rs_prison) { + if (pr->pr_prison_racct == rule->rr_subject.rs_prison_racct) { match = 1; break; } @@ -1144,11 +1141,11 @@ rctl_rule_to_sbuf(struct sbuf *sb, const struct rctl_rule *rule) rule->rr_subject.rs_loginclass->lc_name); break; case RCTL_SUBJECT_TYPE_JAIL: - if (rule->rr_subject.rs_prison == NULL) + if (rule->rr_subject.rs_prison_racct == NULL) sbuf_printf(sb, ":"); else sbuf_printf(sb, "%s:", - rule->rr_subject.rs_prison->pr_name); + rule->rr_subject.rs_prison_racct->prr_name); break; default: panic("rctl_rule_to_sbuf: unknown subject type %d", @@ -1245,7 +1242,7 @@ rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) struct proc *p; struct uidinfo *uip; struct loginclass *lc; - struct prison *pr; + struct prison_racct *prr; error = priv_check(td, PRIV_RCTL_GET_RACCT); if (error != 0) @@ -1256,11 +1253,9 @@ rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) return (error); sx_slock(&allproc_lock); - sx_slock(&allprison_lock); error = rctl_string_to_rule(inputstr, &filter); free(inputstr, M_RCTL); if (error != 0) { - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } @@ -1295,19 +1290,18 @@ rctl_get_racct(struct thread *td, struct rctl_get_racct_args *uap) outputsbuf = rctl_racct_to_sbuf(lc->lc_racct, 1); break; case RCTL_SUBJECT_TYPE_JAIL: - pr = filter->rr_subject.rs_prison; - if (pr == NULL) { + prr = filter->rr_subject.rs_prison_racct; + if (prr == NULL) { error = EINVAL; goto out; } - outputsbuf = rctl_racct_to_sbuf(pr->pr_racct, 1); + outputsbuf = rctl_racct_to_sbuf(prr->prr_racct, 1); break; default: error = EINVAL; } out: rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); if (error != 0) return (error); @@ -1354,11 +1348,9 @@ rctl_get_rules(struct thread *td, struct rctl_get_rules_args *uap) return (error); sx_slock(&allproc_lock); - sx_slock(&allprison_lock); error = rctl_string_to_rule(inputstr, &filter); free(inputstr, M_RCTL); if (error != 0) { - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } @@ -1406,7 +1398,6 @@ again: error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); free(buf, M_RCTL); return (error); @@ -1431,30 +1422,25 @@ rctl_get_limits(struct thread *td, struct rctl_get_limits_args *uap) return (error); sx_slock(&allproc_lock); - sx_slock(&allprison_lock); error = rctl_string_to_rule(inputstr, &filter); free(inputstr, M_RCTL); if (error != 0) { - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } if (filter->rr_subject_type == RCTL_SUBJECT_TYPE_UNDEFINED) { rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (EINVAL); } if (filter->rr_subject_type != RCTL_SUBJECT_TYPE_PROCESS) { rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (EOPNOTSUPP); } if (filter->rr_subject.rs_proc == NULL) { rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (EINVAL); } @@ -1486,7 +1472,6 @@ again: error = rctl_write_outbuf(sb, uap->outbufp, uap->outbuflen); rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); free(buf, M_RCTL); return (error); @@ -1508,11 +1493,9 @@ rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) return (error); sx_slock(&allproc_lock); - sx_slock(&allprison_lock); error = rctl_string_to_rule(inputstr, &rule); free(inputstr, M_RCTL); if (error != 0) { - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } @@ -1532,7 +1515,6 @@ rctl_add_rule(struct thread *td, struct rctl_add_rule_args *uap) out: rctl_rule_release(rule); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } @@ -1553,18 +1535,15 @@ rctl_remove_rule(struct thread *td, struct rctl_remove_rule_args *uap) return (error); sx_slock(&allproc_lock); - sx_slock(&allprison_lock); error = rctl_string_to_rule(inputstr, &filter); free(inputstr, M_RCTL); if (error != 0) { - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); } error = rctl_rule_remove(filter); rctl_rule_release(filter); - sx_sunlock(&allprison_lock); sx_sunlock(&allproc_lock); return (error); @@ -1580,12 +1559,12 @@ rctl_proc_ucred_changed(struct proc *p, struct ucred *newcred) struct rctl_rule_link *link, *newlink; struct uidinfo *newuip; struct loginclass *newlc; - struct prison *newpr; + struct prison_racct *newprr; LIST_HEAD(, rctl_rule_link) newrules; newuip = newcred->cr_ruidinfo; newlc = newcred->cr_loginclass; - newpr = newcred->cr_prison; + newprr = newcred->cr_prison->pr_prison_racct; LIST_INIT(&newrules); @@ -1605,7 +1584,7 @@ again: rulecnt++; LIST_FOREACH(link, &newlc->lc_racct->r_rule_links, rrl_next) rulecnt++; - LIST_FOREACH(link, &newpr->pr_racct->r_rule_links, rrl_next) + LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) rulecnt++; rw_runlock(&rctl_lock); @@ -1655,7 +1634,7 @@ again: rulecnt--; } - LIST_FOREACH(link, &newpr->pr_racct->r_rule_links, rrl_next) { + LIST_FOREACH(link, &newprr->prr_racct->r_rule_links, rrl_next) { if (newlink == NULL) goto goaround; rctl_rule_acquire(link->rrl_rule); |