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