summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_resource.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 57ee671..51b66f4 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -80,6 +80,8 @@ static int donice(struct thread *td, struct proc *chgp, int n);
static struct uidinfo *uilookup(uid_t uid);
static void ruxagg_locked(struct rusage_ext *rux, struct thread *td);
+static __inline int lim_shared(struct plimit *limp);
+
/*
* Resource controls and accounting.
*/
@@ -677,21 +679,29 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
limp->rlim_max = RLIM_INFINITY;
oldssiz.rlim_cur = 0;
- newlim = lim_alloc();
+ newlim = NULL;
PROC_LOCK(p);
+ if (lim_shared(p->p_limit)) {
+ PROC_UNLOCK(p);
+ newlim = lim_alloc();
+ PROC_LOCK(p);
+ }
oldlim = p->p_limit;
alimp = &oldlim->pl_rlimit[which];
if (limp->rlim_cur > alimp->rlim_max ||
limp->rlim_max > alimp->rlim_max)
if ((error = priv_check(td, PRIV_PROC_SETRLIMIT))) {
PROC_UNLOCK(p);
- lim_free(newlim);
+ if (newlim != NULL)
+ lim_free(newlim);
return (error);
}
if (limp->rlim_cur > limp->rlim_max)
limp->rlim_cur = limp->rlim_max;
- lim_copy(newlim, oldlim);
- alimp = &newlim->pl_rlimit[which];
+ if (newlim != NULL) {
+ lim_copy(newlim, oldlim);
+ alimp = &newlim->pl_rlimit[which];
+ }
switch (which) {
@@ -741,9 +751,11 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which,
if (p->p_sysent->sv_fixlimit != NULL)
p->p_sysent->sv_fixlimit(limp, which);
*alimp = *limp;
- p->p_limit = newlim;
+ if (newlim != NULL)
+ p->p_limit = newlim;
PROC_UNLOCK(p);
- lim_free(oldlim);
+ if (newlim != NULL)
+ lim_free(oldlim);
if (which == RLIMIT_STACK) {
/*
@@ -1129,6 +1141,14 @@ lim_hold(limp)
return (limp);
}
+static __inline int
+lim_shared(limp)
+ struct plimit *limp;
+{
+
+ return (limp->pl_refcnt > 1);
+}
+
void
lim_fork(struct proc *p1, struct proc *p2)
{
@@ -1162,7 +1182,7 @@ lim_copy(dst, src)
struct plimit *dst, *src;
{
- KASSERT(dst->pl_refcnt == 1, ("lim_copy to shared limit"));
+ KASSERT(!lim_shared(dst), ("lim_copy to shared limit"));
bcopy(src->pl_rlimit, dst->pl_rlimit, sizeof(src->pl_rlimit));
}
OpenPOWER on IntegriCloud