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 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 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 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 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 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 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