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