PERFORCE change 169582 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Sun Oct 18 20:32:01 UTC 2009
http://p4web.freebsd.org/chv.cgi?CH=169582
Change 169582 by trasz at trasz_victim on 2009/10/18 20:31:35
Working container hierarchy.
Affected files ...
.. //depot/projects/soc2009/trasz_limits/sys/kern/init_main.c#17 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#70 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#39 edit
Differences ...
==== //depot/projects/soc2009/trasz_limits/sys/kern/init_main.c#17 (text+ko) ====
@@ -477,6 +477,9 @@
#endif
td->td_ucred = crhold(p->p_ucred);
+ /* Let the HRL know about the new process. */
+ hrl_proc_init(p);
+
/* Create sigacts. */
p->p_sigacts = sigacts_alloc();
==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#70 (text+ko) ====
@@ -386,37 +386,6 @@
}
}
-#ifdef DIAGNOSTIC
-/*
- * Go through the resource usage info and verify that it makes sense.
- */
-static void
-hrl_assert_proc(const struct proc *p __unused)
-{
- int resource;
- struct ucred *cred;
- struct prison *pr;
-
- cred = p->p_ucred;
- mtx_assert(&hrl_lock, MA_OWNED);
- for (resource = 0; resource <= HRL_RESOURCE_MAX; resource++)
- KASSERT(p->p_container.hc_resources[resource] >= 0,
- ("resource usage propagation meltdown"));
- KASSERT(cred->cr_ruidinfo->ui_container.hc_resources[resource] >= 0,
- ("resource usage propagation meltdown"));
- KASSERT(cred->cr_ruidinfo->ui_container.hc_resources[resource] >=
- p->p_container.hc_resources[resource],
- ("resource usage propagation meltdown"));
- for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) {
- KASSERT(pr->pr_container.hc_resources[resource] >= 0,
- ("resource usage propagation meltdown"));
- KASSERT(pr->pr_container.hc_resources[resource] >=
- p->p_container.hc_resources[resource],
- ("resource usage propagation meltdown"));
- }
-}
-#endif /* DIAGNOSTIC */
-
static void
hrl_container_add(struct hrl_container *dest, const struct hrl_container *src)
{
@@ -426,12 +395,12 @@
for (i = 0; i <= HRL_RESOURCE_MAX; i++) {
KASSERT(dest->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: dest < 0"));
KASSERT(src->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: src < 0"));
dest->hc_resources[i] += src->hc_resources[i];
KASSERT(dest->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: dest < 0 after addition"));
}
}
@@ -444,63 +413,70 @@
for (i = 0; i <= HRL_RESOURCE_MAX; i++) {
KASSERT(dest->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: dest < 0"));
KASSERT(src->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: src < 0"));
KASSERT(src->hc_resources[i] <= dest->hc_resources[i],
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: src > dest"));
dest->hc_resources[i] -= src->hc_resources[i];
KASSERT(dest->hc_resources[i] >= 0,
- ("resource usage propagation meltdown"));
+ ("resource usage propagation meltdown: dest < 0 after subtraction"));
}
}
static void
hrl_container_join(struct hrl_container *child, struct hrl_container *parent)
{
- struct hrl_container *container;
+ int i;
mtx_assert(&hrl_lock, MA_OWNED);
KASSERT(child != NULL, ("child != NULL"));
KASSERT(parent != NULL, ("parent != NULL"));
- LIST_FOREACH(container, &child->hc_parents, hc_next)
- KASSERT(container != parent, ("container already joined"));
-
- LIST_INSERT_HEAD(&child->hc_parents, parent, hc_next);
- hrl_container_add(parent, child);
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ KASSERT(child->hc_parents[i] != parent,
+ ("container already joined"));
+ if (child->hc_parents[i] == NULL) {
+ child->hc_parents[i] = parent;
+ hrl_container_add(parent, child);
+ return;
+ }
+ }
+ panic("container has too many parents");
}
static void
hrl_container_leave(struct hrl_container *child, struct hrl_container *parent)
{
- struct hrl_container *container, *containertmp;
+ int i;
mtx_assert(&hrl_lock, MA_OWNED);
KASSERT(child != NULL, ("child != NULL"));
KASSERT(parent != NULL, ("parent != NULL"));
- hrl_container_subtract(parent, child);
- LIST_FOREACH_SAFE(container, &child->hc_parents, hc_next, containertmp) {
- if (container != parent)
- continue;
- LIST_REMOVE(container, hc_next);
- break;
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ if (child->hc_parents[i] == parent) {
+ hrl_container_subtract(parent, child);
+ child->hc_parents[i] = NULL;
+ return;
+ }
}
+ panic("container not joined");
}
static void
hrl_container_leave_parents(struct hrl_container *child)
{
- struct hrl_container *parent;
+ int i;
mtx_assert(&hrl_lock, MA_OWNED);
KASSERT(child != NULL, ("child != NULL"));
- while (!LIST_EMPTY(&child->hc_parents)) {
- parent = LIST_FIRST(&child->hc_parents);
- hrl_container_subtract(parent, child);
- LIST_REMOVE(parent, hc_next);
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ if (child->hc_parents[i] == NULL)
+ continue;
+ hrl_container_subtract(child->hc_parents[i], child);
+ child->hc_parents[i] = NULL;
}
}
@@ -511,9 +487,10 @@
for (i = 0; i <= HRL_RESOURCE_MAX; i++)
KASSERT(container->hc_resources[i] == 0,
- ("container not zeroed"));
-
- LIST_INIT(&container->hc_parents);
+ ("container->hc_resources[%d] != NULL", i));
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++)
+ KASSERT(container->hc_parents[i] == NULL,
+ ("container->hc_parents[%d] != NULL", i));
}
void
@@ -535,6 +512,63 @@
mtx_unlock(&hrl_lock);
}
+#ifdef DIAGNOSTIC
+/*
+ * Go through the resource consumption information and make sure it makes sense.
+ */
+static void
+hrl_container_assert(const struct hrl_container *container)
+{
+ int i, resource;
+ struct hrl_container *parent;
+
+ mtx_assert(&hrl_lock, MA_OWNED);
+ KASSERT(container != NULL, ("NULL container"));
+
+ for (resource = 0; resource <= HRL_RESOURCE_MAX; resource++) {
+ KASSERT(container->hc_resources[resource] >= 0,
+ ("resource usage propagation meltdown: resource < 0"));
+ }
+
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ parent = container->hc_parents[i];
+ if (parent == NULL);
+ continue;
+ hrl_container_assert(parent);
+ for (resource = 0; resource <= HRL_RESOURCE_MAX; resource++) {
+ KASSERT(parent->hc_resources[resource] >=
+ container->hc_resources[resource],
+ ("resource usage propagation meltdown: child > parent"));
+ }
+ }
+}
+#endif /* DIAGNOSTIC */
+
+/*
+ * Increase consumption of 'resource' by 'amount' for 'container'
+ * and all its parents. Differently from other cases, 'amount' here
+ * may be less than zero.
+ */
+static void
+hrl_container_alloc_resource(struct hrl_container *container, int resource,
+ uint64_t amount)
+{
+ int i;
+
+ mtx_assert(&hrl_lock, MA_OWNED);
+ KASSERT(container != NULL, ("NULL container"));
+
+ container->hc_resources[resource] += amount;
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ if (container->hc_parents[i] == NULL)
+ continue;
+ hrl_container_alloc_resource(container->hc_parents[i], resource, amount);
+ }
+#ifdef DIAGNOSTIC
+ hrl_container_assert(container);
+#endif
+}
+
/*
* Increase allocation of 'resource' by 'amount' for process 'p'.
* Return 0 if it's below limits, or errno, if it's not.
@@ -543,31 +577,21 @@
hrl_alloc(struct proc *p, int resource, uint64_t amount)
{
int error;
- struct ucred *cred;
- struct prison *pr;
- KASSERT(amount > 0, ("hrl_alloc: invalid amount for %s: %ju",
- hrl_resource_name(resource), amount));
-
#if 0
printf("hrl_alloc: allocating %ju of %s for %s (pid %d)\n", amount, hrl_resource_name(resource), p->p_comm, p->p_pid);
#endif
+ KASSERT(amount > 0, ("hrl_alloc: invalid amount for %s: %ju",
+ hrl_resource_name(resource), amount));
+
mtx_lock(&hrl_lock);
error = hrl_enforce_proc(p, resource, amount);
if (error) {
mtx_unlock(&hrl_lock);
return (error);
}
- p->p_container.hc_resources[resource] += amount;
- cred = p->p_ucred;
- cred->cr_ruidinfo->ui_container.hc_resources[resource] += amount;
- for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
- pr->pr_container.hc_resources[resource] += amount;
- cred->cr_loginclass->lc_container.hc_resources[resource] += amount;
-#ifdef DIAGNOSTIC
- hrl_assert_proc(p);
-#endif
+ hrl_container_alloc_resource(&p->p_container, resource, amount);
mtx_unlock(&hrl_lock);
return (0);
@@ -585,16 +609,14 @@
{
int error;
int64_t diff;
- struct ucred *cred;
- struct prison *pr;
- KASSERT(amount >= 0, ("hrl_allocated: invalid amount for %s: %ju",
- hrl_resource_name(resource), amount));
-
#if 0
printf("hrl_allocated: allocated %lld of %s for %s (pid %d)\n", amount, hrl_resource_name(resource), p->p_comm, p->p_pid);
#endif
+ KASSERT(amount >= 0, ("hrl_allocated: invalid amount for %s: %ju",
+ hrl_resource_name(resource), amount));
+
mtx_lock(&hrl_lock);
diff = amount - p->p_container.hc_resources[resource];
if (diff > 0) {
@@ -604,15 +626,7 @@
return (error);
}
}
- p->p_container.hc_resources[resource] = amount;
- cred = p->p_ucred;
- cred->cr_ruidinfo->ui_container.hc_resources[resource] += diff;
- for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
- pr->pr_container.hc_resources[resource] += diff;
- cred->cr_loginclass->lc_container.hc_resources[resource] += diff;
-#ifdef DIAGNOSTIC
- hrl_assert_proc(p);
-#endif
+ hrl_container_alloc_resource(&p->p_container, resource, diff);
mtx_unlock(&hrl_lock);
return (0);
@@ -624,30 +638,21 @@
void
hrl_free(struct proc *p, int resource, uint64_t amount)
{
- struct ucred *cred;
- struct prison *pr;
-
- KASSERT(amount > 0, ("hrl_free: invalid amount for %s: %ju",
- hrl_resource_name(resource), amount));
#if 0
printf("hrl_free: freeing %lld of %s for %s (pid %d)\n", amount, hrl_resource_name(resource), p->p_comm, p->p_pid);
#endif
+ KASSERT(amount > 0, ("hrl_free: invalid amount for %s: %ju",
+ hrl_resource_name(resource), amount));
+
mtx_lock(&hrl_lock);
KASSERT(amount <= p->p_container.hc_resources[resource],
("hrl_free: freeing %ju of %s, which is more than allocated "
"%ld for %s (pid %d)", amount, hrl_resource_name(resource),
p->p_container.hc_resources[resource], p->p_comm, p->p_pid));
- p->p_container.hc_resources[resource] -= amount;
- cred = p->p_ucred;
- cred->cr_ruidinfo->ui_container.hc_resources[resource] -= amount;
- for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
- pr->pr_container.hc_resources[resource] -= amount;
- cred->cr_loginclass->lc_container.hc_resources[resource] -= amount;
-#ifdef DIAGNOSTIC
- hrl_assert_proc(p);
-#endif
+
+ hrl_container_alloc_resource(&p->p_container, resource, -amount);
mtx_unlock(&hrl_lock);
}
@@ -1380,7 +1385,7 @@
struct sbuf *sb;
sb = sbuf_new_auto();
- for (i = 1; i <= HRL_RESOURCE_MAX; i++) {
+ for (i = 0; i <= HRL_RESOURCE_MAX; i++) {
sbuf_printf(sb, "%s=%jd,", hrl_resource_name(i),
container->hc_resources[i]);
}
@@ -1697,6 +1702,24 @@
}
/*
+ * Called from kern/init_main.c, for proc0 and initproc.
+ */
+void
+hrl_proc_init(struct proc *p)
+{
+ struct ucred *cred = p->p_ucred;
+
+ mtx_lock(&hrl_lock);
+
+ hrl_container_create(&p->p_container);
+ hrl_container_join(&p->p_container, &cred->cr_ruidinfo->ui_container);
+ hrl_container_join(&p->p_container, &cred->cr_loginclass->lc_container);
+ hrl_container_join(&p->p_container, &cred->cr_prison->pr_container);
+
+ mtx_unlock(&hrl_lock);
+}
+
+/*
* Called before credentials change, to adjust HRL data structures
* assigned to the process.
*/
@@ -1794,11 +1817,24 @@
int error, i;
struct hrl_limit *limit;
struct hrl_rule *rule;
+ struct hrl_container *container;
PROC_LOCK(parent);
PROC_LOCK(child);
mtx_lock(&hrl_lock);
+ /*
+ * Create container for the child process and inherit containing
+ * containers from the parent.
+ */
+ hrl_container_create(&child->p_container);
+ for (i = 0; i <= HRL_HC_PARENTS_MAX; i++) {
+ container = parent->p_container.hc_parents[i];
+ if (container == NULL)
+ continue;
+ hrl_container_join(&child->p_container, container);
+ }
+
for (i = 0; i <= HRL_RESOURCE_MAX; i++) {
if (parent->p_container.hc_resources[i] != 0 &&
hrl_resource_inheritable(i))
@@ -1806,6 +1842,11 @@
parent->p_container.hc_resources[i]);
}
+ /*
+ * Go through limits applicable to the parent and assign them to the child.
+ * Rules with 'process' subject have to be duplicated in order to make their
+ * hr_subject point to the new process.
+ */
LIST_FOREACH(limit, &parent->p_limits, hl_next) {
if (limit->hl_rule->hr_subject_type == HRL_SUBJECT_TYPE_PROCESS) {
rule = hrl_rule_duplicate(limit->hl_rule, M_NOWAIT);
@@ -1830,8 +1871,6 @@
void
hrl_proc_exiting(struct proc *p)
{
- int i;
-
/*
* XXX: Free these three some other way.
*/
@@ -1840,10 +1879,7 @@
hrl_allocated(p, HRL_RESOURCE_PTY, 0);
mtx_lock(&hrl_lock);
- for (i = 0; i <= HRL_RESOURCE_MAX; i++) {
- KASSERT(p->p_container.hc_resources[i] == 0,
- ("dead process still holding resources"));
- }
+ hrl_container_destroy(&p->p_container);
mtx_unlock(&hrl_lock);
}
==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#39 (text+ko) ====
@@ -123,6 +123,8 @@
#define HRL_AMOUNT_UNDEFINED -1
+#define HRL_HC_PARENTS_MAX 32
+
/*
* 'hrl_container' defines resource consumption for a particular
* subject, such as process or jail. Containers form a graph - each
@@ -139,9 +141,8 @@
* is HRL_SUBJECT_TYPE_USER.
*/
struct hrl_container {
- LIST_ENTRY(hrl_container) hc_next;
int64_t hc_resources[HRL_RESOURCE_MAX + 1];
- LIST_HEAD(, hrl_container) hc_parents;
+ struct hrl_container *hc_parents[HRL_HC_PARENTS_MAX + 1];
};
/*
@@ -164,6 +165,7 @@
void hrl_proc_exiting(struct proc *p);
+void hrl_proc_init(struct proc *p);
void hrl_proc_ucred_changing(struct proc *p, struct ucred *newcred);
struct hrl_rule *hrl_rule_alloc(int flags);
More information about the p4-projects
mailing list