diff options
author | mjg <mjg@FreeBSD.org> | 2015-06-10 10:48:12 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2015-06-10 10:48:12 +0000 |
commit | d7bc9285a673d676370f95a84ce93ef553c8688c (patch) | |
tree | dbbb077ee034cbfe839c1ba19dbe5ce374a5c6a3 | |
parent | 67f2eebb44e1f27017750eddaf5a5ea513cb9c71 (diff) | |
download | FreeBSD-src-d7bc9285a673d676370f95a84ce93ef553c8688c.zip FreeBSD-src-d7bc9285a673d676370f95a84ce93ef553c8688c.tar.gz |
Implement lockless resource limits.
Use the same scheme implemented to manage credentials.
Code needing to look at process's credentials (as opposed to thred's) is
provided with *_proc variants of relevant functions.
Places which possibly had to take the proc lock anyway still use the proc
pointer to access limits.
37 files changed, 152 insertions, 173 deletions
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index f9c11ca..1c54c5c 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -615,7 +615,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK - - lim_cur(p, RLIMIT_STACK); + lim_cur_proc(p, RLIMIT_STACK); PROC_UNLOCK(p); } diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 65d27ba..fa5feaf 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -383,7 +383,7 @@ linux_uselib(struct thread *td, struct linux_uselib_args *args) */ PROC_LOCK(td->td_proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(td->td_proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(td->td_proc, RLIMIT_DATA) || racct_set(td->td_proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(td->td_proc); @@ -1420,7 +1420,6 @@ int linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) { struct l_rlimit rlim; - struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; @@ -1437,9 +1436,7 @@ linux_old_getrlimit(struct thread *td, struct linux_old_getrlimit_args *args) if (which == -1) return (EINVAL); - PROC_LOCK(p); - lim_rlimit(p, which, &bsd_rlim); - PROC_UNLOCK(p); + lim_rlimit(td, which, &bsd_rlim); #ifdef COMPAT_LINUX32 rlim.rlim_cur = (unsigned int)bsd_rlim.rlim_cur; @@ -1464,7 +1461,6 @@ int linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) { struct l_rlimit rlim; - struct proc *p = td->td_proc; struct rlimit bsd_rlim; u_int which; @@ -1481,9 +1477,7 @@ linux_getrlimit(struct thread *td, struct linux_getrlimit_args *args) if (which == -1) return (EINVAL); - PROC_LOCK(p); - lim_rlimit(p, which, &bsd_rlim); - PROC_UNLOCK(p); + lim_rlimit(td, which, &bsd_rlim); rlim.rlim_cur = (l_ulong)bsd_rlim.rlim_cur; rlim.rlim_max = (l_ulong)bsd_rlim.rlim_max; @@ -2204,7 +2198,7 @@ linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args) if (args->old != NULL) { PROC_LOCK(p); - lim_rlimit(p, which, &rlim); + lim_rlimit_proc(p, which, &rlim); PROC_UNLOCK(p); if (rlim.rlim_cur == RLIM_INFINITY) lrlim.rlim_cur = LINUX_RLIM_INFINITY; diff --git a/sys/compat/svr4/imgact_svr4.c b/sys/compat/svr4/imgact_svr4.c index f3bb09e..e61b49b 100644 --- a/sys/compat/svr4/imgact_svr4.c +++ b/sys/compat/svr4/imgact_svr4.c @@ -109,7 +109,7 @@ exec_svr4_imgact(imgp) */ PROC_LOCK(imgp->proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index c0da170..1b4a35e 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -910,9 +910,7 @@ svr4_sys_ulimit(td, uap) switch (uap->cmd) { case SVR4_GFILLIM: - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512; - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_FSIZE) / 512; if (*retval == -1) *retval = 0x7fffffff; return 0; @@ -922,17 +920,13 @@ svr4_sys_ulimit(td, uap) struct rlimit krl; krl.rlim_cur = uap->newlimit * 512; - PROC_LOCK(td->td_proc); - krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE); - PROC_UNLOCK(td->td_proc); + krl.rlim_max = lim_max(td, RLIMIT_FSIZE); error = kern_setrlimit(td, RLIMIT_FSIZE, &krl); if (error) return error; - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_FSIZE); - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_FSIZE); if (*retval == -1) *retval = 0x7fffffff; return 0; @@ -943,9 +937,7 @@ svr4_sys_ulimit(td, uap) struct vmspace *vm = td->td_proc->p_vmspace; register_t r; - PROC_LOCK(td->td_proc); - r = lim_cur(td->td_proc, RLIMIT_DATA); - PROC_UNLOCK(td->td_proc); + r = lim_cur(td, RLIMIT_DATA); if (r == -1) r = 0x7fffffff; @@ -957,9 +949,7 @@ svr4_sys_ulimit(td, uap) } case SVR4_GDESLIM: - PROC_LOCK(td->td_proc); - *retval = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(td->td_proc); + *retval = lim_cur(td, RLIMIT_NOFILE); if (*retval == -1) *retval = 0x7fffffff; return 0; diff --git a/sys/compat/svr4/svr4_resource.c b/sys/compat/svr4/svr4_resource.c index efa0bcf..667ee88 100644 --- a/sys/compat/svr4/svr4_resource.c +++ b/sys/compat/svr4/svr4_resource.c @@ -130,9 +130,7 @@ svr4_sys_getrlimit(td, uap) if (rl == -1) return EINVAL; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &blim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &blim); /* * Our infinity, is their maxfiles. @@ -181,9 +179,7 @@ svr4_sys_setrlimit(td, uap) if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0) return error; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &curlim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &curlim); /* * if the limit is SVR4_RLIM_INFINITY, then we set it to our @@ -228,9 +224,7 @@ svr4_sys_getrlimit64(td, uap) if (rl == -1) return EINVAL; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &blim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &blim); /* * Our infinity, is their maxfiles. @@ -279,9 +273,7 @@ svr4_sys_setrlimit64(td, uap) if ((error = copyin(uap->rlp, &slim, sizeof(slim))) != 0) return error; - PROC_LOCK(td->td_proc); - lim_rlimit(td->td_proc, rl, &curlim); - PROC_UNLOCK(td->td_proc); + lim_rlimit(td, rl, &curlim); /* * if the limit is SVR4_RLIM64_INFINITY, then we set it to our diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c index a473031..3a5e070 100644 --- a/sys/dev/drm2/i915/i915_gem.c +++ b/sys/dev/drm2/i915/i915_gem.c @@ -1874,7 +1874,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data, map = &p->p_vmspace->vm_map; size = round_page(args->size); PROC_LOCK(p); - if (map->size + size > lim_cur(p, RLIMIT_VMEM)) { + if (map->size + size > lim_cur_proc(p, RLIMIT_VMEM)) { PROC_UNLOCK(p); error = -ENOMEM; goto out; diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c index d3d8ce0..f379c5a 100644 --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -199,9 +199,7 @@ fdesc_statfs(mp, sbp) * limit is ever reduced below the current number * of open files... ] */ - PROC_LOCK(td->td_proc); - lim = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(td->td_proc); + lim = lim_cur(td, RLIMIT_NOFILE); fdp = td->td_proc->p_fd; FILEDESC_SLOCK(fdp); limit = racct_get_limit(td->td_proc, RACCT_NOFILE); diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c index 2c2cae4..c4dba20 100644 --- a/sys/i386/ibcs2/ibcs2_misc.c +++ b/sys/i386/ibcs2/ibcs2_misc.c @@ -98,40 +98,30 @@ ibcs2_ulimit(td, uap) struct ibcs2_ulimit_args *uap; { struct rlimit rl; - struct proc *p; int error; #define IBCS2_GETFSIZE 1 #define IBCS2_SETFSIZE 2 #define IBCS2_GETPSIZE 3 #define IBCS2_GETDTABLESIZE 4 - p = td->td_proc; switch (uap->cmd) { case IBCS2_GETFSIZE: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE); if (td->td_retval[0] == -1) td->td_retval[0] = 0x7fffffff; return 0; case IBCS2_SETFSIZE: - PROC_LOCK(p); - rl.rlim_max = lim_max(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + rl.rlim_max = lim_max(td, RLIMIT_FSIZE); rl.rlim_cur = uap->newlimit; error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); if (!error) { - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_FSIZE); } else { DPRINTF(("failed ")); } return error; case IBCS2_GETPSIZE: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_RSS); /* XXX */ return 0; case IBCS2_GETDTABLESIZE: uap->cmd = IBCS2_SC_OPEN_MAX; @@ -801,18 +791,14 @@ ibcs2_sysconf(td, uap) struct ibcs2_sysconf_args *uap; { int mib[2], value, len, error; - struct proc *p; - p = td->td_proc; switch(uap->name) { case IBCS2_SC_ARG_MAX: mib[1] = KERN_ARGMAX; break; case IBCS2_SC_CHILD_MAX: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_NPROC); return 0; case IBCS2_SC_CLK_TCK: @@ -824,9 +810,7 @@ ibcs2_sysconf(td, uap) break; case IBCS2_SC_OPEN_MAX: - PROC_LOCK(p); - td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); - PROC_UNLOCK(p); + td->td_retval[0] = lim_cur(td, RLIMIT_NOFILE); return 0; case IBCS2_SC_JOB_CONTROL: diff --git a/sys/i386/linux/imgact_linux.c b/sys/i386/linux/imgact_linux.c index 0a4114b..9363b47 100644 --- a/sys/i386/linux/imgact_linux.c +++ b/sys/i386/linux/imgact_linux.c @@ -108,7 +108,7 @@ exec_linux_imgact(struct image_params *imgp) */ PROC_LOCK(imgp->proc); if (a_out->a_text > maxtsiz || - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index c9f969b..4fb5785 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -509,7 +509,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot, */ PROC_LOCK(p); p->p_vmspace->vm_maxsaddr = (char *)USRSTACK - - lim_cur(p, RLIMIT_STACK); + lim_cur_proc(p, RLIMIT_STACK); PROC_UNLOCK(p); } diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c index edd5f5f..3165ac0 100644 --- a/sys/kern/imgact_aout.c +++ b/sys/kern/imgact_aout.c @@ -248,7 +248,7 @@ exec_aout_imgact(struct image_params *imgp) a_out->a_text > maxtsiz || /* data + bss can't exceed rlimit */ - a_out->a_data + bss_size > lim_cur(imgp->proc, RLIMIT_DATA) || + a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) || racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) { PROC_UNLOCK(imgp->proc); return (ENOMEM); diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index c3953fe..0675128 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -908,11 +908,11 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * not actually fault in all the segments pages. */ PROC_LOCK(imgp->proc); - if (data_size > lim_cur(imgp->proc, RLIMIT_DATA)) + if (data_size > lim_cur_proc(imgp->proc, RLIMIT_DATA)) err_str = "Data segment size exceeds process limit"; else if (text_size > maxtsiz) err_str = "Text segment size exceeds system limit"; - else if (total_size > lim_cur(imgp->proc, RLIMIT_VMEM)) + else if (total_size > lim_cur_proc(imgp->proc, RLIMIT_VMEM)) err_str = "Total segment size exceeds process limit"; else if (racct_set(imgp->proc, RACCT_DATA, data_size) != 0) err_str = "Data segment size exceeds resource limit"; @@ -936,7 +936,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) * calculation is that it leaves room for the heap to grow to * its maximum allowed size. */ - addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(imgp->proc, + addr = round_page((vm_offset_t)vmspace->vm_daddr + lim_max(curthread, RLIMIT_DATA)); PROC_UNLOCK(imgp->proc); @@ -1983,7 +1983,7 @@ note_procstat_rlimit(void *arg, struct sbuf *sb, size_t *sizep) sbuf_bcat(sb, &structsize, sizeof(structsize)); PROC_LOCK(p); for (i = 0; i < RLIM_NLIMITS; i++) - lim_rlimit(p, i, &rlim[i]); + lim_rlimit_proc(p, i, &rlim[i]); PROC_UNLOCK(p); sbuf_bcat(sb, rlim, sizeof(rlim)); } diff --git a/sys/kern/imgact_gzip.c b/sys/kern/imgact_gzip.c index ab77a88..47b7280 100644 --- a/sys/kern/imgact_gzip.c +++ b/sys/kern/imgact_gzip.c @@ -212,7 +212,7 @@ do_aout_hdr(struct imgact_gzip * gz) /* data + bss can't exceed rlimit */ gz->a_out.a_data + gz->bss_size > - lim_cur(gz->ip->proc, RLIMIT_DATA) || + lim_cur_proc(gz->ip->proc, RLIMIT_DATA) || racct_set(gz->ip->proc, RACCT_DATA, gz->a_out.a_data + gz->bss_size) != 0) { PROC_UNLOCK(gz->ip->proc); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 98a15d8..d16f3f9 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -109,7 +109,7 @@ static void fdgrowtable(struct filedesc *fdp, int nfd); static void fdgrowtable_exp(struct filedesc *fdp, int nfd); static void fdunused(struct filedesc *fdp, int fd); static void fdused(struct filedesc *fdp, int fd); -static int getmaxfd(struct proc *p); +static int getmaxfd(struct thread *td); /* Flags for do_dup() */ #define DUP_FIXED 0x1 /* Force fixed allocation. */ @@ -328,16 +328,19 @@ struct getdtablesize_args { int sys_getdtablesize(struct thread *td, struct getdtablesize_args *uap) { - struct proc *p = td->td_proc; +#ifdef RACCT uint64_t lim; +#endif - PROC_LOCK(p); td->td_retval[0] = - min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); + min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc); +#ifdef RACCT + PROC_LOCK(p); lim = racct_get_limit(td->td_proc, RACCT_NOFILE); PROC_UNLOCK(p); if (lim < td->td_retval[0]) td->td_retval[0] = lim; +#endif return (0); } @@ -780,15 +783,10 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } static int -getmaxfd(struct proc *p) +getmaxfd(struct thread *td) { - int maxfd; - - PROC_LOCK(p); - maxfd = min((int)lim_cur(p, RLIMIT_NOFILE), maxfilesperproc); - PROC_UNLOCK(p); - return (maxfd); + return (min((int)lim_cur(td, RLIMIT_NOFILE), maxfilesperproc)); } /* @@ -816,7 +814,7 @@ do_dup(struct thread *td, int flags, int old, int new) return (EBADF); if (new < 0) return (flags & DUP_FCNTL ? EINVAL : EBADF); - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); if (new >= maxfd) return (flags & DUP_FCNTL ? EINVAL : EBADF); @@ -1616,7 +1614,7 @@ fdalloc(struct thread *td, int minfd, int *result) if (fdp->fd_freefile > minfd) minfd = fdp->fd_freefile; - maxfd = getmaxfd(p); + maxfd = getmaxfd(td); /* * Search the bitmap for a free descriptor starting at minfd. diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 9000add..ff17fe9 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -754,14 +754,10 @@ kern_kqueue(struct thread *td, int flags) p = td->td_proc; cred = td->td_ucred; crhold(cred); - PROC_LOCK(p); - if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td->td_proc, - RLIMIT_KQUEUES))) { - PROC_UNLOCK(p); + if (!chgkqcnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_KQUEUES))) { crfree(cred); return (ENOMEM); } - PROC_UNLOCK(p); fdp = p->p_fd; error = falloc(td, &fp, &fd, flags); diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 8668f0d..d3ae4f0 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1073,7 +1073,7 @@ exec_new_vmspace(imgp, sv) if (imgp->stack_sz != 0) { ssiz = trunc_page(imgp->stack_sz); PROC_LOCK(p); - lim_rlimit(p, RLIMIT_STACK, &rlim_stack); + lim_rlimit_proc(p, RLIMIT_STACK, &rlim_stack); PROC_UNLOCK(p); if (ssiz > rlim_stack.rlim_max) ssiz = rlim_stack.rlim_max; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 835b497..3fd4f09 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -912,10 +912,8 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, if (error == 0) ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, 0); else { - PROC_LOCK(p1); ok = chgproccnt(td->td_ucred->cr_ruidinfo, 1, - lim_cur(p1, RLIMIT_NPROC)); - PROC_UNLOCK(p1); + lim_cur(td, RLIMIT_NPROC)); } if (ok) { do_fork(td, flags, newproc, td2, vm2, pdflags); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index fc33feb..27c6f40 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2615,7 +2615,7 @@ sysctl_kern_proc_rlimit(SYSCTL_HANDLER_ARGS) */ if (req->oldptr != NULL) { PROC_LOCK(p); - lim_rlimit(p, which, &rlim); + lim_rlimit_proc(p, which, &rlim); PROC_UNLOCK(p); } error = SYSCTL_OUT(req, &rlim, sizeof(rlim)); diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index dac49cd..546f3b2 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -560,15 +560,11 @@ ogetrlimit(struct thread *td, register struct ogetrlimit_args *uap) { struct orlimit olim; struct rlimit rl; - struct proc *p; int error; if (uap->which >= RLIM_NLIMITS) return (EINVAL); - p = td->td_proc; - PROC_LOCK(p); - lim_rlimit(p, uap->which, &rl); - PROC_UNLOCK(p); + lim_rlimit(td, uap->which, &rl); /* * XXX would be more correct to convert only RLIM_INFINITY to the @@ -625,7 +621,7 @@ lim_cb(void *arg) } PROC_STATUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { - lim_rlimit(p, RLIMIT_CPU, &rlim); + lim_rlimit_proc(p, RLIMIT_CPU, &rlim); if (p->p_rux.rux_runtime >= rlim.rlim_max * cpu_tickrate()) { killproc(p, "exceeded maximum CPU limit"); } else { @@ -667,29 +663,21 @@ kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, limp->rlim_max = RLIM_INFINITY; oldssiz.rlim_cur = 0; - newlim = NULL; + newlim = lim_alloc(); 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); - if (newlim != NULL) - lim_free(newlim); + lim_free(newlim); return (error); } if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; - if (newlim != NULL) { - lim_copy(newlim, oldlim); - alimp = &newlim->pl_rlimit[which]; - } + lim_copy(newlim, oldlim); + alimp = &newlim->pl_rlimit[which]; switch (which) { @@ -739,11 +727,10 @@ 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; - if (newlim != NULL) - p->p_limit = newlim; + p->p_limit = newlim; + PROC_UPDATE_COW(p); PROC_UNLOCK(p); - if (newlim != NULL) - lim_free(oldlim); + lim_free(oldlim); if (which == RLIMIT_STACK && /* @@ -793,15 +780,11 @@ int sys_getrlimit(struct thread *td, register struct __getrlimit_args *uap) { struct rlimit rlim; - struct proc *p; int error; if (uap->which >= RLIM_NLIMITS) return (EINVAL); - p = td->td_proc; - PROC_LOCK(p); - lim_rlimit(p, uap->which, &rlim); - PROC_UNLOCK(p); + lim_rlimit(td, uap->which, &rlim); error = copyout(&rlim, uap->rlp, sizeof(struct rlimit)); return (error); } @@ -1172,11 +1155,20 @@ lim_copy(struct plimit *dst, struct plimit *src) * which parameter specifies the index into the rlimit array. */ rlim_t -lim_max(struct proc *p, int which) +lim_max(struct thread *td, int which) { struct rlimit rl; - lim_rlimit(p, which, &rl); + lim_rlimit(td, which, &rl); + return (rl.rlim_max); +} + +rlim_t +lim_max_proc(struct proc *p, int which) +{ + struct rlimit rl; + + lim_rlimit_proc(p, which, &rl); return (rl.rlim_max); } @@ -1185,11 +1177,20 @@ lim_max(struct proc *p, int which) * The which parameter which specifies the index into the rlimit array */ rlim_t -lim_cur(struct proc *p, int which) +lim_cur(struct thread *td, int which) { struct rlimit rl; - lim_rlimit(p, which, &rl); + lim_rlimit(td, which, &rl); + return (rl.rlim_cur); +} + +rlim_t +lim_cur_proc(struct proc *p, int which) +{ + struct rlimit rl; + + lim_rlimit_proc(p, which, &rl); return (rl.rlim_cur); } @@ -1198,7 +1199,20 @@ lim_cur(struct proc *p, int which) * specified by 'which' in the rlimit structure pointed to by 'rlp'. */ void -lim_rlimit(struct proc *p, int which, struct rlimit *rlp) +lim_rlimit(struct thread *td, int which, struct rlimit *rlp) +{ + struct proc *p = td->td_proc; + + MPASS(td == curthread); + KASSERT(which >= 0 && which < RLIM_NLIMITS, + ("request for invalid resource limit")); + *rlp = td->td_limit->pl_rlimit[which]; + if (p->p_sysent->sv_fixlimit != NULL) + p->p_sysent->sv_fixlimit(rlp, which); +} + +void +lim_rlimit_proc(struct proc *p, int which, struct rlimit *rlp) { PROC_LOCK_ASSERT(p, MA_OWNED); @@ -1441,3 +1455,17 @@ chgkqcnt(struct uidinfo *uip, int diff, rlim_t max) } return (1); } + +void +lim_update_thread(struct thread *td) +{ + struct proc *p; + struct plimit *lim; + + p = td->td_proc; + lim = td->td_limit; + PROC_LOCK_ASSERT(p, MA_OWNED); + td->td_limit = lim_hold(p->p_limit); + if (lim != NULL) + lim_free(lim); +} diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5d48060..b70da5b 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -3309,7 +3309,7 @@ coredump(struct thread *td) * a corefile is truncated instead of not being created, * if it is larger than the limit. */ - limit = (off_t)lim_cur(p, RLIMIT_CORE); + limit = (off_t)lim_cur(td, RLIMIT_CORE); if (limit == 0 || racct_get_available(p, RACCT_CORE) == 0) { PROC_UNLOCK(p); return (EFBIG); diff --git a/sys/kern/kern_syscalls.c b/sys/kern/kern_syscalls.c index 3d3df01..15574be 100644 --- a/sys/kern/kern_syscalls.c +++ b/sys/kern/kern_syscalls.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <sys/module.h> #include <sys/mutex.h> #include <sys/proc.h> +#include <sys/resourcevar.h> #include <sys/sx.h> #include <sys/syscall.h> #include <sys/sysent.h> diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 2e97553..4343b64 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -389,6 +389,7 @@ thread_cow_get_proc(struct thread *newtd, struct proc *p) PROC_LOCK_ASSERT(p, MA_OWNED); newtd->td_ucred = crhold(p->p_ucred); + newtd->td_limit = lim_hold(p->p_limit); newtd->td_cowgen = p->p_cowgen; } @@ -397,6 +398,7 @@ thread_cow_get(struct thread *newtd, struct thread *td) { newtd->td_ucred = crhold(td->td_ucred); + newtd->td_limit = lim_hold(td->td_limit); newtd->td_cowgen = td->td_cowgen; } @@ -406,6 +408,8 @@ thread_cow_free(struct thread *td) if (td->td_ucred) crfree(td->td_ucred); + if (td->td_limit) + lim_free(td->td_limit); } void @@ -417,6 +421,8 @@ thread_cow_update(struct thread *td) PROC_LOCK(p); if (td->td_ucred != p->p_ucred) cred_update_thread(td); + if (td->td_limit != p->p_limit) + lim_update_thread(td); td->td_cowgen = p->p_cowgen; PROC_UNLOCK(p); } diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index 410085e..aac6eb6 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -409,10 +409,8 @@ copyout_map(struct thread *td, vm_offset_t *addr, size_t sz) /* * Map somewhere after heap in process memory. */ - PROC_LOCK(td->td_proc); *addr = round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)); - PROC_UNLOCK(td->td_proc); + lim_max(td, RLIMIT_DATA)); /* round size up to page boundry */ size = (vm_size_t)round_page(sz); diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 3240a5f..3eb126b 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -382,7 +382,7 @@ kern_shmat_locked(struct thread *td, int shmid, const void *shmaddr, */ PROC_LOCK(p); attach_va = round_page((vm_offset_t)p->p_vmspace->vm_daddr + - lim_max(p, RLIMIT_DATA)); + lim_max_proc(p, RLIMIT_DATA)); PROC_UNLOCK(p); } diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 2d1e8fe..fcc9c47 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -741,7 +741,7 @@ pts_alloc(int fflags, struct thread *td, struct file *fp) PROC_UNLOCK(p); return (EAGAIN); } - ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(p, RLIMIT_NPTS)); + ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); if (!ok) { racct_sub(p, RACCT_NPTS, 1); PROC_UNLOCK(p); @@ -795,7 +795,7 @@ pts_alloc_external(int fflags, struct thread *td, struct file *fp, PROC_UNLOCK(p); return (EAGAIN); } - ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(p, RLIMIT_NPTS)); + ok = chgptscnt(cred->cr_ruidinfo, 1, lim_cur(td, RLIMIT_NPTS)); if (!ok) { racct_sub(p, RACCT_NPTS, 1); PROC_UNLOCK(p); diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 88952ed..243450d 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -420,9 +420,7 @@ sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so, if (cc > sb_max_adj) return (0); if (td != NULL) { - PROC_LOCK(td->td_proc); - sbsize_limit = lim_cur(td->td_proc, RLIMIT_SBSIZE); - PROC_UNLOCK(td->td_proc); + sbsize_limit = lim_cur(td, RLIMIT_SBSIZE); } else sbsize_limit = RLIM_INFINITY; if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 573d009..0b073b9 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -2106,19 +2106,18 @@ vn_vget_ino_gen(struct vnode *vp, vn_get_ino_t alloc, void *alloc_arg, int vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio, - const struct thread *td) + struct thread *td) { if (vp->v_type != VREG || td == NULL) return (0); - PROC_LOCK(td->td_proc); if ((uoff_t)uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { + lim_cur(td, RLIMIT_FSIZE)) { + PROC_LOCK(td->td_proc); kern_psignal(td->td_proc, SIGXFSZ); PROC_UNLOCK(td->td_proc); return (EFBIG); } - PROC_UNLOCK(td->td_proc); return (0); } diff --git a/sys/ofed/drivers/infiniband/core/umem.c b/sys/ofed/drivers/infiniband/core/umem.c index cdd2e67..5f4465f 100644 --- a/sys/ofed/drivers/infiniband/core/umem.c +++ b/sys/ofed/drivers/infiniband/core/umem.c @@ -272,7 +272,7 @@ struct ib_umem *ib_umem_get_ex(struct ib_ucontext *context, unsigned long addr, PROC_LOCK(proc); if (ptoa(npages + pmap_wired_count(vm_map_pmap(&proc->p_vmspace->vm_map))) > - lim_cur(proc, RLIMIT_MEMLOCK)) { + lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); kfree(umem); return ERR_PTR(-ENOMEM); diff --git a/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c b/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c index 0cdebaf..ad5818e 100644 --- a/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/sys/ofed/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -553,7 +553,8 @@ out: proc = curproc; pmap = vm_map_pmap(&proc->p_vmspace->vm_map); PROC_LOCK(proc); - if (ptoa(pmap_wired_count(pmap) + 1) > lim_cur(proc, RLIMIT_MEMLOCK)) { + if (ptoa(pmap_wired_count(pmap) + 1) > + lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); ret = -ENOMEM; goto out; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 3e694e1..e6c83b4 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -246,6 +246,7 @@ struct thread { int td_intr_nesting_level; /* (k) Interrupt recursion. */ int td_pinned; /* (k) Temporary cpu pin count. */ struct ucred *td_ucred; /* (k) Reference to credentials. */ + struct plimit *td_limit; /* (k) Resource limits. */ u_int td_estcpu; /* (t) estimated cpu utilization */ int td_slptick; /* (t) Time at sleep. */ int td_blktick; /* (t) Time spent blocked. */ @@ -499,7 +500,7 @@ struct proc { struct filedesc *p_fd; /* (b) Open files. */ struct filedesc_to_leader *p_fdtol; /* (b) Tracking node */ struct pstats *p_stats; /* (b) Accounting/statistics (CPU). */ - struct plimit *p_limit; /* (c) Process limits. */ + struct plimit *p_limit; /* (c) Resource limits. */ struct callout p_limco; /* (c) Limit callout handle */ struct sigacts *p_sigacts; /* (x) Signal actions, state (CPU). */ diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h index a07fdf8..b4c707d 100644 --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -130,13 +130,16 @@ int kern_proc_setrlimit(struct thread *td, struct proc *p, u_int which, struct plimit *lim_alloc(void); void lim_copy(struct plimit *dst, struct plimit *src); -rlim_t lim_cur(struct proc *p, int which); +rlim_t lim_cur(struct thread *td, int which); +rlim_t lim_cur_proc(struct proc *p, int which); void lim_fork(struct proc *p1, struct proc *p2); void lim_free(struct plimit *limp); struct plimit *lim_hold(struct plimit *limp); -rlim_t lim_max(struct proc *p, int which); -void lim_rlimit(struct proc *p, int which, struct rlimit *rlp); +rlim_t lim_max(struct thread *td, int which); +rlim_t lim_max_proc(struct proc *p, int which); +void lim_rlimit(struct thread *td, int which, struct rlimit *rlp); +void lim_rlimit_proc(struct proc *p, int which, struct rlimit *rlp); void ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2, struct rusage_ext *rux2); void rucollect(struct rusage *ru, struct rusage *ru2); @@ -156,5 +159,7 @@ void ui_racct_foreach(void (*callback)(struct racct *racct, void *arg2, void *arg3), void *arg2, void *arg3); #endif +void lim_update_thread(struct thread *td); + #endif /* _KERNEL */ #endif /* !_SYS_RESOURCEVAR_H_ */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index a30130f..36ef8af 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -692,7 +692,7 @@ int vn_rdwr_inchunks(enum uio_rw rw, struct vnode *vp, void *base, struct ucred *active_cred, struct ucred *file_cred, size_t *aresid, struct thread *td); int vn_rlimit_fsize(const struct vnode *vn, const struct uio *uio, - const struct thread *td); + struct thread *td); int vn_stat(struct vnode *vp, struct stat *sb, struct ucred *active_cred, struct ucred *file_cred, struct thread *td); int vn_start_write(struct vnode *vp, struct mount **mpp, int flags); diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index 3005491..5ade2bc 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -224,16 +224,14 @@ swap_reserve_by_cred(vm_ooffset_t incr, struct ucred *cred) mtx_unlock(&sw_dev_mtx); if (res) { - PROC_LOCK(curproc); UIDINFO_VMSIZE_LOCK(uip); if ((overcommit & SWAP_RESERVE_RLIMIT_ON) != 0 && - uip->ui_vmsize + incr > lim_cur(curproc, RLIMIT_SWAP) && + uip->ui_vmsize + incr > lim_cur(curthread, RLIMIT_SWAP) && priv_check(curthread, PRIV_VM_SWAP_NORLIMIT)) res = 0; else uip->ui_vmsize += incr; UIDINFO_VMSIZE_UNLOCK(uip); - PROC_UNLOCK(curproc); if (!res) { mtx_lock(&sw_dev_mtx); swap_reserved -= incr; diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index bad9994..12ebf5d 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -3424,10 +3424,8 @@ vm_map_stack(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, growsize = sgrowsiz; init_ssize = (max_ssize < growsize) ? max_ssize : growsize; vm_map_lock(map); - PROC_LOCK(curproc); - lmemlim = lim_cur(curproc, RLIMIT_MEMLOCK); - vmemlim = lim_cur(curproc, RLIMIT_VMEM); - PROC_UNLOCK(curproc); + lmemlim = lim_cur(curthread, RLIMIT_MEMLOCK); + vmemlim = lim_cur(curthread, RLIMIT_VMEM); if (!old_mlock && map->flags & MAP_WIREFUTURE) { if (ptoa(pmap_wired_count(map->pmap)) + init_ssize > lmemlim) { rv = KERN_NO_SPACE; @@ -3556,12 +3554,10 @@ vm_map_growstack(struct proc *p, vm_offset_t addr) int error; #endif + lmemlim = lim_cur(curthread, RLIMIT_MEMLOCK); + stacklim = lim_cur(curthread, RLIMIT_STACK); + vmemlim = lim_cur(curthread, RLIMIT_VMEM); Retry: - PROC_LOCK(p); - lmemlim = lim_cur(p, RLIMIT_MEMLOCK); - stacklim = lim_cur(p, RLIMIT_STACK); - vmemlim = lim_cur(p, RLIMIT_VMEM); - PROC_UNLOCK(p); vm_map_lock_read(map); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 489a987..d331a9b 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -316,9 +316,9 @@ sys_mmap(td, uap) if (addr == 0 || (addr >= round_page((vm_offset_t)vms->vm_taddr) && addr < round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)))) + lim_max_proc(td->td_proc, RLIMIT_DATA)))) addr = round_page((vm_offset_t)vms->vm_daddr + - lim_max(td->td_proc, RLIMIT_DATA)); + lim_max_proc(td->td_proc, RLIMIT_DATA)); PROC_UNLOCK(td->td_proc); } if (size == 0) { @@ -1028,7 +1028,7 @@ vm_mlock(struct proc *proc, struct ucred *cred, const void *addr0, size_t len) map = &proc->p_vmspace->vm_map; PROC_LOCK(proc); nsize = ptoa(npages + pmap_wired_count(map->pmap)); - if (nsize > lim_cur(proc, RLIMIT_MEMLOCK)) { + if (nsize > lim_cur_proc(proc, RLIMIT_MEMLOCK)) { PROC_UNLOCK(proc); return (ENOMEM); } @@ -1088,7 +1088,7 @@ sys_mlockall(td, uap) */ if (!old_mlock && uap->how & MCL_CURRENT) { PROC_LOCK(td->td_proc); - if (map->size > lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { + if (map->size > lim_cur(td, RLIMIT_MEMLOCK)) { PROC_UNLOCK(td->td_proc); return (ENOMEM); } @@ -1481,7 +1481,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, if (map == &td->td_proc->p_vmspace->vm_map) { PROC_LOCK(td->td_proc); - if (map->size + size > lim_cur(td->td_proc, RLIMIT_VMEM)) { + if (map->size + size > lim_cur_proc(td->td_proc, RLIMIT_VMEM)) { PROC_UNLOCK(td->td_proc); return (ENOMEM); } @@ -1491,7 +1491,7 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, } if (!old_mlock && map->flags & MAP_WIREFUTURE) { if (ptoa(pmap_wired_count(map->pmap)) + size > - lim_cur(td->td_proc, RLIMIT_MEMLOCK)) { + lim_cur_proc(td->td_proc, RLIMIT_MEMLOCK)) { racct_set_force(td->td_proc, RACCT_VMEM, map->size); PROC_UNLOCK(td->td_proc); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 2f57579..71d76d4 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1851,7 +1851,7 @@ again: /* * get a limit */ - lim_rlimit(p, RLIMIT_RSS, &rsslim); + lim_rlimit_proc(p, RLIMIT_RSS, &rsslim); limit = OFF_TO_IDX( qmin(rsslim.rlim_cur, rsslim.rlim_max)); diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c index cc77ff7..201c13b 100644 --- a/sys/vm/vm_unix.c +++ b/sys/vm/vm_unix.c @@ -83,11 +83,9 @@ sys_obreak(td, uap) int error = 0; boolean_t do_map_wirefuture; - PROC_LOCK(td->td_proc); - datalim = lim_cur(td->td_proc, RLIMIT_DATA); - lmemlim = lim_cur(td->td_proc, RLIMIT_MEMLOCK); - vmemlim = lim_cur(td->td_proc, RLIMIT_VMEM); - PROC_UNLOCK(td->td_proc); + datalim = lim_cur(td, RLIMIT_DATA); + lmemlim = lim_cur(td, RLIMIT_MEMLOCK); + vmemlim = lim_cur(td, RLIMIT_VMEM); do_map_wirefuture = FALSE; new = round_page((vm_offset_t)uap->nsize); |