Date: Sat, 20 Jun 2009 14:02:29 GMT From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 164758 for review Message-ID: <200906201402.n5KE2TKi012952@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=164758 Change 164758 by trasz@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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906201402.n5KE2TKi012952>