xref: /illumos-gate/usr/src/uts/common/syscall/rlimit.c (revision dc32d872)
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