From owner-p4-projects@FreeBSD.ORG Wed Jul 7 21:48:21 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 1E04410657AA; Wed, 7 Jul 2010 21:48:21 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D55BA1065798 for ; Wed, 7 Jul 2010 21:48:20 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id C344F8FC19 for ; Wed, 7 Jul 2010 21:48:20 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o67LmK6x062255 for ; Wed, 7 Jul 2010 21:48:20 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o67LmKj5062253 for perforce@freebsd.org; Wed, 7 Jul 2010 21:48:20 GMT (envelope-from trasz@freebsd.org) Date: Wed, 7 Jul 2010 21:48:20 GMT Message-Id: <201007072148.o67LmKj5062253@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 180612 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Jul 2010 21:48:21 -0000 http://p4web.freebsd.org/@@180612?ac=10 Change 180612 by trasz@trasz_victim on 2010/07/07 21:47:39 container_join() needs to be able to return error, should the resources used by the joining container push resource usage in parent container above is limits. Make it so. Affected files ... .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#7 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_fork.c#17 edit .. //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#79 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/container.h#5 edit .. //depot/projects/soc2009/trasz_limits/sys/sys/proc.h#23 edit Differences ... ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_container.c#7 (text+ko) ==== @@ -57,7 +57,7 @@ struct mtx container_lock; MTX_SYSINIT(container_lock, &container_lock, "container lock", MTX_RECURSE); /* XXX: Make it non-recurseable later. */ -static void +static int container_add(struct container *dest, const struct container *src) { int i; @@ -69,10 +69,19 @@ ("resource usage propagation meltdown: dest < 0")); KASSERT(src->c_resources[i] >= 0, ("resource usage propagation meltdown: src < 0")); + /* + * XXX: Container hierarchy! + */ + /* + * XXX: Enforce limit here; if exceeded, undo everything + * and return error. + */ dest->c_resources[i] += src->c_resources[i]; KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0 after addition")); } + + return (0); } static void @@ -90,15 +99,18 @@ KASSERT(src->c_resources[i] <= dest->c_resources[i], ("resource usage propagation meltdown: src > dest")); dest->c_resources[i] -= src->c_resources[i]; + /* + * XXX: Container hierarchy! + */ KASSERT(dest->c_resources[i] >= 0, ("resource usage propagation meltdown: dest < 0 after subtraction")); } } -void +int container_join(struct container *child, struct container *parent) { - int i; + int i, error; mtx_assert(&container_lock, MA_OWNED); KASSERT(child != NULL, ("child != NULL")); @@ -108,9 +120,12 @@ KASSERT(child->c_parents[i] != parent, ("container already joined")); if (child->c_parents[i] == NULL) { + error = container_add(parent, child); + if (error) + return (error); + child->c_parents[i] = parent; - container_add(parent, child); - return; + return (0); } } panic("container has too many parents"); @@ -362,13 +377,13 @@ } /* - * Inherit resource usage information and copy limits from the parent - * process to the child. + * Inherit resource usage information and containing containers + * from the parent process. */ -void +int container_proc_fork(struct proc *parent, struct proc *child) { - int i; + int i, error = 0; struct container *container; PROC_LOCK(parent); @@ -379,22 +394,44 @@ * Create container for the child process and inherit containing * containers from the parent. */ + bzero(&child->p_container, sizeof(child->p_container)); container_create(&child->p_container); for (i = 0; i <= CONTAINER_PARENTS_MAX; i++) { container = parent->p_container.c_parents[i]; if (container == NULL) continue; - container_join(&child->p_container, container); + error = container_join(&child->p_container, container); + if (error) { + container_destroy(&child->p_container); + goto out; + } } + /* + * Inherit resource usage. + */ for (i = 0; i <= RUSAGE_MAX; i++) { - if (parent->p_container.c_resources[i] != 0 && - container_resource_inheritable(i)) - rusage_set(child, i, - parent->p_container.c_resources[i]); + if (parent->p_container.c_resources[i] == 0 || + !container_resource_inheritable(i)) + continue; + + error = rusage_set(child, i, parent->p_container.c_resources[i]); + if (error) { + /* + * XXX: The only purpose of these two lines is to prevent from + * tripping checks in container_leave_parents(). + */ + for (i = 0; i <= RUSAGE_MAX; i++) + rusage_set(child, i, 0); + container_destroy(&child->p_container); + goto out; + } } +out: mtx_unlock(&container_lock); PROC_UNLOCK(child); PROC_UNLOCK(parent); + + return (error); } ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_fork.c#17 (text+ko) ==== @@ -351,6 +351,15 @@ } /* + * Initialize resource container for the child process. + */ + error = container_proc_fork(p1, newproc); + if (error) { + error = EAGAIN; + goto fail; + } + + /* * Increment the count of procs running with this uid. Don't allow * a nonprivileged user to exceed their current limit. * @@ -739,11 +748,6 @@ } /* - * Initialize resource container for the child process. - */ - container_proc_fork(p1, p2); - - /* * Both processes are set up, now check if any loadable modules want * to adjust anything. * What if they have an error? XXX @@ -798,6 +802,7 @@ *procp = p2; return (0); fail: + container_proc_exit(newproc); sx_sunlock(&proctree_lock); if (ppsratecheck(&lastfail, &curfail, 1)) printf("maxproc limit exceeded by uid %i, please see tuning(7) and login.conf(5).\n", ==== //depot/projects/soc2009/trasz_limits/sys/kern/kern_hrl.c#79 (text+ko) ==== @@ -1445,14 +1445,18 @@ void hrl_proc_init(struct proc *p) { + int error; struct ucred *cred = p->p_ucred; mtx_lock(&container_lock); container_create(&p->p_container); - container_join(&p->p_container, &cred->cr_ruidinfo->ui_container); - container_join(&p->p_container, &cred->cr_loginclass->lc_container); - container_join(&p->p_container, &cred->cr_prison->pr_container); + error = container_join(&p->p_container, &cred->cr_ruidinfo->ui_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); + error = container_join(&p->p_container, &cred->cr_loginclass->lc_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); + error = container_join(&p->p_container, &cred->cr_prison->pr_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); mtx_unlock(&container_lock); } @@ -1520,7 +1524,8 @@ } container_leave(&p->p_container, &olduip->ui_container); - container_join(&p->p_container, &newuip->ui_container); + error = container_join(&p->p_container, &newuip->ui_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); } if (newlc != oldlc) { LIST_FOREACH(link, &newlc->lc_container.c_rule_links, hrl_next) { @@ -1529,7 +1534,8 @@ } container_leave(&p->p_container, &oldlc->lc_container); - container_join(&p->p_container, &newlc->lc_container); + error = container_join(&p->p_container, &newlc->lc_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); } if (newpr != oldpr) { LIST_FOREACH(link, &newpr->pr_container.c_rule_links, hrl_next) { @@ -1538,7 +1544,8 @@ } container_leave(&p->p_container, &oldpr->pr_container); - container_join(&p->p_container, &newpr->pr_container); + error = container_join(&p->p_container, &newpr->pr_container); + KASSERT(error == 0, ("hrl_proc_init: better error handling needed")); } mtx_unlock(&container_lock); ==== //depot/projects/soc2009/trasz_limits/sys/sys/container.h#5 (text+ko) ==== @@ -96,10 +96,10 @@ void container_create(struct container *container); void container_destroy(struct container *container); -void container_join(struct container *child, struct container *parent); +int container_join(struct container *child, struct container *parent); void container_leave(struct container *child, struct container *parent); +int container_proc_fork(struct proc *parent, struct proc *child); void container_proc_exit(struct proc *p); -void container_proc_fork(struct proc *parent, struct proc *child); #endif /* !_CONTAINER_H_ */ ==== //depot/projects/soc2009/trasz_limits/sys/sys/proc.h#23 (text+ko) ==== @@ -524,7 +524,6 @@ int p_boundary_count;/* (c) Num threads at user boundary */ int p_pendingcnt; /* how many signals are pending */ struct itimers *p_itimers; /* (c) POSIX interval timers. */ - struct container p_container; /* (*) resource usage accounting */ /* End area that is zeroed on creation. */ #define p_endzero p_magic @@ -558,6 +557,7 @@ LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/ struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */ struct cv p_pwait; /* (*) wait cv for exit/exec */ + struct container p_container; /* (*) resource usage accounting */ }; #define p_session p_pgrp->pg_session