17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/param.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/inttypes.h>
347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
357c478bd9Sstevel@tonic-gate #include <sys/systm.h>
367c478bd9Sstevel@tonic-gate #include <sys/tuneable.h>
377c478bd9Sstevel@tonic-gate #include <sys/user.h>
387c478bd9Sstevel@tonic-gate #include <sys/errno.h>
397c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
407c478bd9Sstevel@tonic-gate #include <sys/file.h>
417c478bd9Sstevel@tonic-gate #include <sys/proc.h>
427c478bd9Sstevel@tonic-gate #include <sys/resource.h>
437c478bd9Sstevel@tonic-gate #include <sys/ulimit.h>
447c478bd9Sstevel@tonic-gate #include <sys/debug.h>
457c478bd9Sstevel@tonic-gate #include <sys/rctl.h>
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate #include <vm/as.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate * Perhaps ulimit could be moved into a user library, as calls to
517c478bd9Sstevel@tonic-gate * getrlimit and setrlimit, were it not for binary compatibility
527c478bd9Sstevel@tonic-gate * restrictions.
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate long
ulimit(int cmd,long arg)557c478bd9Sstevel@tonic-gate ulimit(int cmd, long arg)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate proc_t *p = curproc;
587c478bd9Sstevel@tonic-gate long retval;
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate switch (cmd) {
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate case UL_GFILLIM: /* Return current file size limit. */
637c478bd9Sstevel@tonic-gate {
647c478bd9Sstevel@tonic-gate rlim64_t filesize;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
677c478bd9Sstevel@tonic-gate filesize = rctl_enforced_value(rctlproc_legacy[RLIMIT_FSIZE],
687c478bd9Sstevel@tonic-gate p->p_rctls, p);
697c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_ILP32) {
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate * File size is returned in blocks for ulimit.
747c478bd9Sstevel@tonic-gate * This function is deprecated and therefore LFS API
757c478bd9Sstevel@tonic-gate * didn't define the behaviour of ulimit.
767c478bd9Sstevel@tonic-gate * Here we return maximum value of file size possible
777c478bd9Sstevel@tonic-gate * so that applications that do not check errors
787c478bd9Sstevel@tonic-gate * continue to work.
797c478bd9Sstevel@tonic-gate */
807c478bd9Sstevel@tonic-gate if (filesize > MAXOFF32_T)
817c478bd9Sstevel@tonic-gate filesize = MAXOFF32_T;
827c478bd9Sstevel@tonic-gate retval = ((int)filesize >> SCTRSHFT);
837c478bd9Sstevel@tonic-gate } else
847c478bd9Sstevel@tonic-gate retval = filesize >> SCTRSHFT;
857c478bd9Sstevel@tonic-gate break;
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate case UL_SFILLIM: /* Set new file size limit. */
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate int error = 0;
917c478bd9Sstevel@tonic-gate rlim64_t lim = (rlim64_t)arg;
927c478bd9Sstevel@tonic-gate struct rlimit64 rl64;
937c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp = rctl_rlimit_set_prealloc(1);
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate if (lim >= (((rlim64_t)MAXOFFSET_T) >> SCTRSHFT))
967c478bd9Sstevel@tonic-gate lim = (rlim64_t)RLIM64_INFINITY;
977c478bd9Sstevel@tonic-gate else
987c478bd9Sstevel@tonic-gate lim <<= SCTRSHFT;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate rl64.rlim_max = rl64.rlim_cur = lim;
1017c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
1027c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[RLIMIT_FSIZE], p,
1037c478bd9Sstevel@tonic-gate &rl64, gp, RCTL_LOCAL_DENY | RCTL_LOCAL_SIGNAL, SIGXFSZ,
1047c478bd9Sstevel@tonic-gate CRED())) {
1057c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
1067c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
1077c478bd9Sstevel@tonic-gate return (set_errno(error));
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
1107c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
1117c478bd9Sstevel@tonic-gate retval = arg;
1127c478bd9Sstevel@tonic-gate break;
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate case UL_GMEMLIM: /* Return maximum possible break value. */
1167c478bd9Sstevel@tonic-gate {
1177c478bd9Sstevel@tonic-gate struct seg *seg;
1187c478bd9Sstevel@tonic-gate struct seg *nextseg;
1197c478bd9Sstevel@tonic-gate struct as *as = p->p_as;
1207c478bd9Sstevel@tonic-gate caddr_t brkend;
1217c478bd9Sstevel@tonic-gate caddr_t brkbase;
1227c478bd9Sstevel@tonic-gate size_t size;
1237c478bd9Sstevel@tonic-gate rlim64_t size_ctl;
1247c478bd9Sstevel@tonic-gate rlim64_t vmem_ctl;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * Find the segment with a virtual address
1287c478bd9Sstevel@tonic-gate * greater than the end of the current break.
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate nextseg = NULL;
1317c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
1327c478bd9Sstevel@tonic-gate brkbase = (caddr_t)p->p_brkbase;
1337c478bd9Sstevel@tonic-gate brkend = (caddr_t)p->p_brkbase + p->p_brksize;
1347c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate * Since we can't return less than the current break,
1387c478bd9Sstevel@tonic-gate * initialize the return value to the current break
1397c478bd9Sstevel@tonic-gate */
1407c478bd9Sstevel@tonic-gate retval = (long)brkend;
1417c478bd9Sstevel@tonic-gate
142*dc32d872SJosef 'Jeff' Sipek AS_LOCK_ENTER(as, RW_READER);
1437c478bd9Sstevel@tonic-gate for (seg = as_findseg(as, brkend, 0); seg != NULL;
1447c478bd9Sstevel@tonic-gate seg = AS_SEGNEXT(as, seg)) {
1457c478bd9Sstevel@tonic-gate if (seg->s_base >= brkend) {
1467c478bd9Sstevel@tonic-gate nextseg = seg;
1477c478bd9Sstevel@tonic-gate break;
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
1527c478bd9Sstevel@tonic-gate size_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_DATA],
1537c478bd9Sstevel@tonic-gate p->p_rctls, p);
1547c478bd9Sstevel@tonic-gate vmem_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_VMEM],
1557c478bd9Sstevel@tonic-gate p->p_rctls, p);
1567c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate * First, calculate the maximum break value based on
1607c478bd9Sstevel@tonic-gate * the user's RLIMIT_DATA, but also taking into account
1617c478bd9Sstevel@tonic-gate * that this value cannot be greater than as->a_userlimit.
1627c478bd9Sstevel@tonic-gate * We also take care to make sure that we don't overflow
1637c478bd9Sstevel@tonic-gate * in the calculation.
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate * Since we are casting the RLIMIT_DATA value to a
1677c478bd9Sstevel@tonic-gate * ulong (a 32-bit value in the 32-bit kernel) we have
1687c478bd9Sstevel@tonic-gate * to pass this assertion.
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate ASSERT32((size_t)size_ctl <= UINT32_MAX);
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate size = (size_t)size_ctl;
1737c478bd9Sstevel@tonic-gate if (as->a_userlimit - brkbase > size)
1747c478bd9Sstevel@tonic-gate retval = MAX((size_t)retval, (size_t)(brkbase + size));
1757c478bd9Sstevel@tonic-gate /* don't return less than current */
1767c478bd9Sstevel@tonic-gate else
1777c478bd9Sstevel@tonic-gate retval = (long)as->a_userlimit;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * The max break cannot extend into the next segment
1817c478bd9Sstevel@tonic-gate */
1827c478bd9Sstevel@tonic-gate if (nextseg != NULL)
1837c478bd9Sstevel@tonic-gate retval = MIN((uintptr_t)retval,
1847c478bd9Sstevel@tonic-gate (uintptr_t)nextseg->s_base);
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * Handle the case where there is an limit on RLIMIT_VMEM
1887c478bd9Sstevel@tonic-gate */
1897c478bd9Sstevel@tonic-gate if (vmem_ctl < UINT64_MAX) {
1907c478bd9Sstevel@tonic-gate /* calculate brkend based on the end of page */
1917c478bd9Sstevel@tonic-gate caddr_t brkendpg = (caddr_t)roundup((uintptr_t)brkend,
1927c478bd9Sstevel@tonic-gate PAGESIZE);
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate * Large Files: The following assertion has to pass
1957c478bd9Sstevel@tonic-gate * through to ensure the correctness of the cast.
1967c478bd9Sstevel@tonic-gate */
1977c478bd9Sstevel@tonic-gate ASSERT32(vmem_ctl <= UINT32_MAX);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate size = (size_t)(vmem_ctl & PAGEMASK);
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate if (as->a_size < size)
2027c478bd9Sstevel@tonic-gate size -= as->a_size;
2037c478bd9Sstevel@tonic-gate else
2047c478bd9Sstevel@tonic-gate size = 0;
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate * Take care to not overflow the calculation
2077c478bd9Sstevel@tonic-gate */
2087c478bd9Sstevel@tonic-gate if (as->a_userlimit - brkendpg > size)
2097c478bd9Sstevel@tonic-gate retval = MIN((size_t)retval,
2107c478bd9Sstevel@tonic-gate (size_t)(brkendpg + size));
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
213*dc32d872SJosef 'Jeff' Sipek AS_LOCK_EXIT(as);
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate /* truncate to same boundary as sbrk */
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate switch (get_udatamodel()) {
2187c478bd9Sstevel@tonic-gate default:
2197c478bd9Sstevel@tonic-gate case DATAMODEL_ILP32:
2207c478bd9Sstevel@tonic-gate retval = retval & ~(8-1);
2217c478bd9Sstevel@tonic-gate break;
2227c478bd9Sstevel@tonic-gate case DATAMODEL_LP64:
2237c478bd9Sstevel@tonic-gate retval = retval & ~(16-1);
2247c478bd9Sstevel@tonic-gate break;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate break;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate case UL_GDESLIM: /* Return approximate number of open files */
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate rlim64_t fdno_ctl;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate mutex_enter(&curproc->p_lock);
2347c478bd9Sstevel@tonic-gate fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE],
2357c478bd9Sstevel@tonic-gate curproc->p_rctls, curproc);
2367c478bd9Sstevel@tonic-gate ASSERT(fdno_ctl <= INT_MAX);
2377c478bd9Sstevel@tonic-gate retval = (rlim_t)fdno_ctl;
2387c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock);
2397c478bd9Sstevel@tonic-gate break;
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate default:
2437c478bd9Sstevel@tonic-gate return (set_errno(EINVAL));
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate return (retval);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate int
ulimit32(int cmd,int arg)2527c478bd9Sstevel@tonic-gate ulimit32(int cmd, int arg)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate return ((int)ulimit(cmd, (long)arg));
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate #if defined(_ILP32) || defined(_SYSCALL32_IMPL)
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate * Large Files: getrlimit returns RLIM_SAVED_CUR or RLIM_SAVED_MAX when
2637c478bd9Sstevel@tonic-gate * rlim_cur or rlim_max is not representable in 32-bit rlim_t. These
2647c478bd9Sstevel@tonic-gate * values are just tokens which will be used in setrlimit to set the
2657c478bd9Sstevel@tonic-gate * correct limits. The current limits are saved in the saved_rlimit members
2667c478bd9Sstevel@tonic-gate * in user structures when the token is returned. setrlimit restores
2677c478bd9Sstevel@tonic-gate * the limit values to these saved values when the token is passed.
2687c478bd9Sstevel@tonic-gate * Consider the following common scenario of the apps:
2697c478bd9Sstevel@tonic-gate *
2707c478bd9Sstevel@tonic-gate * limit = getrlimit();
2717c478bd9Sstevel@tonic-gate * savedlimit = limit;
2727c478bd9Sstevel@tonic-gate * limit = limit1;
2737c478bd9Sstevel@tonic-gate * setrlimit(limit)
2747c478bd9Sstevel@tonic-gate * // execute all processes in the new rlimit state.
2757c478bd9Sstevel@tonic-gate * setrlimit(savedlimit) // restore the old values.
2767c478bd9Sstevel@tonic-gate *
2777c478bd9Sstevel@tonic-gate * Most apps don't check error returns from getrlimit or setrlimit
2787c478bd9Sstevel@tonic-gate * and this is why we return tokens when the correct value
2797c478bd9Sstevel@tonic-gate * cannot be represented in rlim_t. For more discussion refer to
2807c478bd9Sstevel@tonic-gate * the LFS API document.
2817c478bd9Sstevel@tonic-gate *
2827c478bd9Sstevel@tonic-gate * In the 64-bit kernel, all existing resource limits are treated in this
2837c478bd9Sstevel@tonic-gate * manner. In the 32-bit kernel, CPU time is treated equivalently to the
2847c478bd9Sstevel@tonic-gate * file size limit above; the VM-related limits are not. The macro,
2857c478bd9Sstevel@tonic-gate * RLIM_SAVED(x), returns true if the resource limit should be handled in
2867c478bd9Sstevel@tonic-gate * this way on the current kernel.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate int
getrlimit32(int resource,struct rlimit32 * rlp)2897c478bd9Sstevel@tonic-gate getrlimit32(int resource, struct rlimit32 *rlp)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate struct rlimit32 rlim32;
2927c478bd9Sstevel@tonic-gate struct rlimit64 rlim64;
2937c478bd9Sstevel@tonic-gate struct proc *p = curproc;
2947c478bd9Sstevel@tonic-gate struct user *up = PTOU(p);
2957c478bd9Sstevel@tonic-gate int savecur = 0;
2967c478bd9Sstevel@tonic-gate int savemax = 0;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS)
2997c478bd9Sstevel@tonic-gate return (set_errno(EINVAL));
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3027c478bd9Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[resource], p, &rlim64);
3037c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate if (rlim64.rlim_max > (rlim64_t)UINT32_MAX) {
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (rlim64.rlim_max == RLIM64_INFINITY)
3087c478bd9Sstevel@tonic-gate rlim32.rlim_max = RLIM32_INFINITY;
3097c478bd9Sstevel@tonic-gate else {
3107c478bd9Sstevel@tonic-gate savemax = 1;
3117c478bd9Sstevel@tonic-gate rlim32.rlim_max = RLIM32_SAVED_MAX;
3127c478bd9Sstevel@tonic-gate /*CONSTCOND*/
3137c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource));
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate if (rlim64.rlim_cur == RLIM64_INFINITY)
3177c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_INFINITY;
3187c478bd9Sstevel@tonic-gate else if (rlim64.rlim_cur == rlim64.rlim_max) {
3197c478bd9Sstevel@tonic-gate savecur = 1;
3207c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_SAVED_MAX;
3217c478bd9Sstevel@tonic-gate /*CONSTCOND*/
3227c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource));
3237c478bd9Sstevel@tonic-gate } else if (rlim64.rlim_cur > (rlim64_t)UINT32_MAX) {
3247c478bd9Sstevel@tonic-gate savecur = 1;
3257c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_SAVED_CUR;
3267c478bd9Sstevel@tonic-gate /*CONSTCOND*/
3277c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource));
3287c478bd9Sstevel@tonic-gate } else
3297c478bd9Sstevel@tonic-gate rlim32.rlim_cur = rlim64.rlim_cur;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * save the current limits in user structure.
3337c478bd9Sstevel@tonic-gate */
3347c478bd9Sstevel@tonic-gate /*CONSTCOND*/
3357c478bd9Sstevel@tonic-gate if (RLIM_SAVED(resource)) {
3367c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3377c478bd9Sstevel@tonic-gate if (savemax)
3387c478bd9Sstevel@tonic-gate up->u_saved_rlimit[resource].rlim_max =
3397c478bd9Sstevel@tonic-gate rlim64.rlim_max;
3407c478bd9Sstevel@tonic-gate if (savecur)
3417c478bd9Sstevel@tonic-gate up->u_saved_rlimit[resource].rlim_cur =
3427c478bd9Sstevel@tonic-gate rlim64.rlim_cur;
3437c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate } else {
3467c478bd9Sstevel@tonic-gate ASSERT(rlim64.rlim_cur <= (rlim64_t)UINT32_MAX);
3477c478bd9Sstevel@tonic-gate rlim32.rlim_max = rlim64.rlim_max;
3487c478bd9Sstevel@tonic-gate rlim32.rlim_cur = rlim64.rlim_cur;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate if (copyout(&rlim32, rlp, sizeof (rlim32)))
3527c478bd9Sstevel@tonic-gate return (set_errno(EFAULT));
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate return (0);
3557c478bd9Sstevel@tonic-gate }
3567c478bd9Sstevel@tonic-gate
3577c478bd9Sstevel@tonic-gate /*
3587c478bd9Sstevel@tonic-gate * See comments above getrlimit32(). When the tokens are passed in the
3597c478bd9Sstevel@tonic-gate * rlimit structure the values are considered equal to the values
3607c478bd9Sstevel@tonic-gate * stored in saved_rlimit members of user structure.
3617c478bd9Sstevel@tonic-gate * When the user passes RLIM_INFINITY to set the resource limit to
3627c478bd9Sstevel@tonic-gate * unlimited internally understand this value as RLIM64_INFINITY and
3637c478bd9Sstevel@tonic-gate * let rlimit() do the job.
3647c478bd9Sstevel@tonic-gate */
3657c478bd9Sstevel@tonic-gate int
setrlimit32(int resource,struct rlimit32 * rlp)3667c478bd9Sstevel@tonic-gate setrlimit32(int resource, struct rlimit32 *rlp)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate struct rlimit32 rlim32;
3697c478bd9Sstevel@tonic-gate struct rlimit64 rlim64;
3707c478bd9Sstevel@tonic-gate struct rlimit64 saved_rlim;
3717c478bd9Sstevel@tonic-gate int error;
3727c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread);
3737c478bd9Sstevel@tonic-gate struct user *up = PTOU(p);
3747c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp;
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS)
3777c478bd9Sstevel@tonic-gate return (set_errno(EINVAL));
3787c478bd9Sstevel@tonic-gate if (copyin(rlp, &rlim32, sizeof (rlim32)))
3797c478bd9Sstevel@tonic-gate return (set_errno(EFAULT));
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate gp = rctl_rlimit_set_prealloc(1);
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate * Disallow resource limit tunnelling
3857c478bd9Sstevel@tonic-gate */
3867c478bd9Sstevel@tonic-gate /*CONSTCOND*/
3877c478bd9Sstevel@tonic-gate if (RLIM_SAVED(resource)) {
3887c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
3897c478bd9Sstevel@tonic-gate saved_rlim = up->u_saved_rlimit[resource];
3907c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
3917c478bd9Sstevel@tonic-gate } else {
3927c478bd9Sstevel@tonic-gate saved_rlim.rlim_max = (rlim64_t)rlim32.rlim_max;
3937c478bd9Sstevel@tonic-gate saved_rlim.rlim_cur = (rlim64_t)rlim32.rlim_cur;
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate switch (rlim32.rlim_cur) {
3977c478bd9Sstevel@tonic-gate case RLIM32_INFINITY:
3987c478bd9Sstevel@tonic-gate rlim64.rlim_cur = RLIM64_INFINITY;
3997c478bd9Sstevel@tonic-gate break;
4007c478bd9Sstevel@tonic-gate case RLIM32_SAVED_CUR:
4017c478bd9Sstevel@tonic-gate rlim64.rlim_cur = saved_rlim.rlim_cur;
4027c478bd9Sstevel@tonic-gate break;
4037c478bd9Sstevel@tonic-gate case RLIM32_SAVED_MAX:
4047c478bd9Sstevel@tonic-gate rlim64.rlim_cur = saved_rlim.rlim_max;
4057c478bd9Sstevel@tonic-gate break;
4067c478bd9Sstevel@tonic-gate default:
4077c478bd9Sstevel@tonic-gate rlim64.rlim_cur = (rlim64_t)rlim32.rlim_cur;
4087c478bd9Sstevel@tonic-gate break;
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate switch (rlim32.rlim_max) {
4127c478bd9Sstevel@tonic-gate case RLIM32_INFINITY:
4137c478bd9Sstevel@tonic-gate rlim64.rlim_max = RLIM64_INFINITY;
4147c478bd9Sstevel@tonic-gate break;
4157c478bd9Sstevel@tonic-gate case RLIM32_SAVED_MAX:
4167c478bd9Sstevel@tonic-gate rlim64.rlim_max = saved_rlim.rlim_max;
4177c478bd9Sstevel@tonic-gate break;
4187c478bd9Sstevel@tonic-gate case RLIM32_SAVED_CUR:
4197c478bd9Sstevel@tonic-gate rlim64.rlim_max = saved_rlim.rlim_cur;
4207c478bd9Sstevel@tonic-gate break;
4217c478bd9Sstevel@tonic-gate default:
4227c478bd9Sstevel@tonic-gate rlim64.rlim_max = (rlim64_t)rlim32.rlim_max;
4237c478bd9Sstevel@tonic-gate break;
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
4277c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[resource], p, &rlim64, gp,
4287c478bd9Sstevel@tonic-gate rctlproc_flags[resource], rctlproc_signals[resource], CRED())) {
4297c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4307c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
4317c478bd9Sstevel@tonic-gate return (set_errno(error));
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4347c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate return (0);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate #endif /* _ILP32 && _SYSCALL32_IMPL */
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate int
getrlimit64(int resource,struct rlimit64 * rlp)4427c478bd9Sstevel@tonic-gate getrlimit64(int resource, struct rlimit64 *rlp)
4437c478bd9Sstevel@tonic-gate {
4447c478bd9Sstevel@tonic-gate struct rlimit64 rlim64;
4457c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread);
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS)
4487c478bd9Sstevel@tonic-gate return (set_errno(EINVAL));
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
4517c478bd9Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[resource], p, &rlim64);
4527c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate if (copyout(&rlim64, rlp, sizeof (rlim64)))
4557c478bd9Sstevel@tonic-gate return (set_errno(EFAULT));
4567c478bd9Sstevel@tonic-gate return (0);
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate int
setrlimit64(int resource,struct rlimit64 * rlp)4607c478bd9Sstevel@tonic-gate setrlimit64(int resource, struct rlimit64 *rlp)
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate struct rlimit64 rlim64;
4637c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread);
4647c478bd9Sstevel@tonic-gate int error;
4657c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS)
4687c478bd9Sstevel@tonic-gate return (set_errno(EINVAL));
4697c478bd9Sstevel@tonic-gate if (copyin(rlp, &rlim64, sizeof (rlim64)))
4707c478bd9Sstevel@tonic-gate return (set_errno(EFAULT));
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate gp = rctl_rlimit_set_prealloc(1);
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock);
4757c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[resource], p, &rlim64, gp,
4767c478bd9Sstevel@tonic-gate rctlproc_flags[resource], rctlproc_signals[resource], CRED())) {
4777c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4787c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
4797c478bd9Sstevel@tonic-gate return (set_errno(error));
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock);
4827c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp);
4837c478bd9Sstevel@tonic-gate return (0);
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate }
486