PERFORCE change 164758 for review

Edward Tomasz Napierala trasz at FreeBSD.org
Sat Jun 20 14:02:30 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=164758

Change 164758 by trasz at trasz_victim on 2009/06/20 14:02:17

	Fix up per-user and per-group resource utilisation when changing
	uids and gids.

Affected files ...

.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#12 edit
.. //depot/projects/soc2009/trasz_limits/sys/kern/kern_prot.c#10 edit
.. //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#9 edit

Differences ...

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#12 (text+ko) ====

@@ -101,6 +101,37 @@
 
 MALLOC_DEFINE(M_HRL, "hrl", "Hierarchical Resource Limits");
 
+#ifdef INVARIANTS
+/*
+ * Go through the accounting info and verify that it makes sense.
+ */
+static void
+hrl_assert_proc(const struct proc *p __unused)
+{
+#ifdef notyet
+	int i, resource;
+	struct ucred *cred;
+	struct prison *pr;
+	
+	cred = p->p_ucred;
+
+	for (resource = 0; resource < HRL_RESOURCE_MAX; resource++)
+		KASSERT(p->p_accounting.ha_resources[resource] >= 0, (""));
+	KASSERT(cred->cr_ruidinfo->ui_accounting.ha_resources[resource] >= 0, (""));
+	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
+		KASSERT(pr->pr_accounting.ha_resources[resource] >= 0, (""));
+	for (i = 0; i < cred->cr_ngroups; i++) {
+		for (resource = 0; resource < HRL_RESOURCE_MAX; resource++)
+			KASSERT(cred->cr_gidinfos[i]->gi_accounting.ha_resources[resource] >= 0, (""));
+	}
+#endif
+}
+#endif /* INVARIANTS */
+
+/*
+ * Increase allocation of 'resource' by 'amount' for process 'p'.
+ * Return 0 if it's below limits, or errno, if it's not.
+ */
 int
 hrl_alloc_proc(struct proc *p, int resource, uint64_t amount)
 {
@@ -116,11 +147,16 @@
 	p->p_accounting.ha_resources[resource] += amount;
 	cred = p->p_ucred;
 	cred->cr_ruidinfo->ui_accounting.ha_resources[resource] += amount;
+	cred->cr_uidinfo->ui_accounting.ha_resources[resource] += amount;
 	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
 		pr->pr_accounting.ha_resources[resource] += amount;
 	for (i = 0; i < cred->cr_ngroups; i++)
 		cred->cr_gidinfos[i]->gi_accounting.ha_resources[resource] += amount;
 
+#ifdef INVARIANTS
+	hrl_assert_proc(p);
+#endif
+
 	/*
 	 * XXX: When denying, return proper errno - EFSIZ, ENOMEM etc.
 	 */
@@ -128,6 +164,13 @@
 	return (0);
 }
 
+/*
+ * Set allocation of 'resource' to 'amount' for process 'p'.
+ * Return 0 if it's below limits, or errno, if it's not.
+ *
+ * Note that decreasing the allocation always returns 0,
+ * even if it's above the limit.
+ */
 int
 hrl_allocated_proc(struct proc *p, int resource, uint64_t amount)
 {
@@ -140,19 +183,22 @@
 	p->p_accounting.ha_resources[resource] += diff;
 	cred = p->p_ucred;
 	cred->cr_ruidinfo->ui_accounting.ha_resources[resource] += diff;
+	cred->cr_uidinfo->ui_accounting.ha_resources[resource] += diff;
 	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
 		pr->pr_accounting.ha_resources[resource] += diff;
 	for (i = 0; i < cred->cr_ngroups; i++)
 		cred->cr_gidinfos[i]->gi_accounting.ha_resources[resource] += diff;
 
-	/*
-	 * XXX: Make sure process can lower its resource consumption,
-	 *      even when already above the limit.
-	 */
+#ifdef INVARIANTS
+	hrl_assert_proc(p);
+#endif
 
 	return (0);
 }
 
+/*
+ * Decrease allocation of 'resource' by 'amount' for process 'p'.
+ */
 void
 hrl_free_proc(struct proc *p, int resource, uint64_t amount)
 {
@@ -165,18 +211,30 @@
 	p->p_accounting.ha_resources[resource] -= amount;
 	cred = p->p_ucred;
 	cred->cr_ruidinfo->ui_accounting.ha_resources[resource] -= amount;
+	cred->cr_uidinfo->ui_accounting.ha_resources[resource] -= amount;
 	for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent)
 		pr->pr_accounting.ha_resources[resource] -= amount;
 	for (i = 0; i < cred->cr_ngroups; i++)
 		cred->cr_gidinfos[i]->gi_accounting.ha_resources[resource] -= amount;
+
+#ifdef INVARIANTS
+	hrl_assert_proc(p);
+#endif
 }
 
+/*
+ * Increase allocation of 'resource' for current process by 'amount'.
+ * Return 0 if it's below limits, or errno, if it's not.
+ */
 int
 hrl_alloc(int resource, uint64_t amount)
 {
 	return (hrl_alloc_proc(curproc, resource, amount));
 }
 
+/*
+ * Decrease allocation of 'resource' for current process by 'amount'.
+ */
 void
 hrl_free(int resource, uint64_t amount)
 {
@@ -226,6 +284,34 @@
 		uma_zfree(hrl_zone, node);
 }
 
+void
+hrl_acc_add(struct hrl_acc *dest, const struct hrl_acc *src)
+{
+	int i;
+
+	for (i = 0; i < HRL_RESOURCE_MAX; i++) {
+			dest->ha_resources[i] += src->ha_resources[i];
+#ifdef notyet
+			KASSERT(src->ha_resources[i] >= 0, (""));
+			KASSERT(dest->ha_resources[i] >= 0, (""));
+#endif
+	}
+}
+
+void
+hrl_acc_subtract(struct hrl_acc *dest, const struct hrl_acc *src)
+{
+	int i;
+
+	for (i = 0; i < HRL_RESOURCE_MAX; i++) {
+			dest->ha_resources[i] -= src->ha_resources[i];
+#ifdef notyet
+			KASSERT(src->ha_resources[i] >= 0, (""));
+			KASSERT(dest->ha_resources[i] >= 0, (""));
+#endif
+	}
+}
+
 /*
  * System calls.
  */

==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_prot.c#10 (text+ko) ====

@@ -566,7 +566,7 @@
 		change_euid(newcred, uip);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	uifree(uip);
 	crfree(oldcred);
@@ -621,7 +621,7 @@
 		change_euid(newcred, euip);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	uifree(euip);
 	crfree(oldcred);
@@ -724,7 +724,7 @@
 		change_egid(newcred, gip);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	gifree(gip);
 	crfree(oldcred);
@@ -775,7 +775,7 @@
 		change_egid(newcred, egip);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	gifree(egip);
 	crfree(oldcred);
@@ -862,7 +862,7 @@
 			newcred->cr_gidinfos[i] = gidinfos[i];
 	}
 	setsugid(p);
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	for (i = 0; i < oldngroups; i++)
 		gifree(oldgidinfos[i]);
@@ -937,7 +937,7 @@
 		change_svuid(newcred, newcred->cr_uid);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	uifree(ruip);
 	uifree(euip);
@@ -1004,7 +1004,7 @@
 		change_svgid(newcred, newcred->cr_groups[0]);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	gifree(egip);
 	crfree(oldcred);
@@ -1081,7 +1081,7 @@
 		change_svuid(newcred, suid);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	uifree(ruip);
 	uifree(euip);
@@ -1160,7 +1160,7 @@
 		change_svgid(newcred, sgid);
 		setsugid(p);
 	}
-	p->p_ucred = newcred;
+	change_cred(p, newcred);
 	PROC_UNLOCK(p);
 	gifree(egip);
 	crfree(oldcred);
@@ -2032,8 +2032,46 @@
 }
 
 /*
- * XXX: All of these need to somehow fixup the resource accounting.
+ * Assign new credential to the process, fixing up HRL accounting
+ * as neccessary.
  */
+void
+change_cred(struct proc *p, struct ucred *newcred)
+{
+	int i;
+	struct uidinfo *olduip, *newuip;
+
+	/*
+	 * Fix up per-euid resource consumption.
+	 */
+	newuip = newcred->cr_uidinfo;
+	olduip = p->p_ucred->cr_uidinfo;
+	if (newuip != olduip) {
+		hrl_acc_subtract(&olduip->ui_accounting, &p->p_accounting);
+		hrl_acc_add(&newuip->ui_accounting, &p->p_accounting);
+	}
+
+	/*
+	 * Fix up per-ruid resource consumption.
+	 */
+	newuip = newcred->cr_ruidinfo;
+	olduip = p->p_ucred->cr_ruidinfo;
+	if (newuip != olduip) {
+		hrl_acc_subtract(&olduip->ui_accounting, &p->p_accounting);
+		hrl_acc_add(&newuip->ui_accounting, &p->p_accounting);
+	}
+
+	/*
+	 * Fix up per-group resource consumption.
+	 */
+	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
+		hrl_acc_subtract(&p->p_ucred->cr_gidinfos[i]->gi_accounting, &p->p_accounting);
+	for (i = 0; i < newcred->cr_ngroups; i++)
+		hrl_acc_add(&newcred->cr_gidinfos[i]->gi_accounting, &p->p_accounting);
+
+	p->p_ucred = newcred;
+}
+
 /*-
  * Change a process's effective uid.
  * Side effects: newcred->cr_uid and newcred->cr_uidinfo will be modified.

==== //depot/projects/soc2009/trasz_limits/sys/sys/hrl.h#9 (text+ko) ====

@@ -118,6 +118,8 @@
 void	hrl_free_proc(struct proc *p, int object, uint64_t amount);
 
 void	hrl_adjust(int subject, id_t subject_id, int per, int resource, int action, int64_t amount);
+void	hrl_acc_add(struct hrl_acc *dest, const struct hrl_acc *src);
+void	hrl_acc_subtract(struct hrl_acc *dest, const struct hrl_acc *src);
 
 #else /* !_KERNEL */
 


More information about the p4-projects mailing list