summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_rctl.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2011-05-03 07:32:58 +0000
committertrasz <trasz@FreeBSD.org>2011-05-03 07:32:58 +0000
commit752ffacc695ca593f052934a2881be57dec92419 (patch)
tree83f996220eb5127d50beee996ac337678876fccc /sys/kern/kern_rctl.c
parenta857ffe8345f7868b2fb1f9f4b0606558ecba6ca (diff)
downloadFreeBSD-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.c95
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);
OpenPOWER on IntegriCloud