1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/inttypes.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/tuneable.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/ulimit.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/rctl.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* 52*7c478bd9Sstevel@tonic-gate * Perhaps ulimit could be moved into a user library, as calls to 53*7c478bd9Sstevel@tonic-gate * getrlimit and setrlimit, were it not for binary compatibility 54*7c478bd9Sstevel@tonic-gate * restrictions. 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate long 57*7c478bd9Sstevel@tonic-gate ulimit(int cmd, long arg) 58*7c478bd9Sstevel@tonic-gate { 59*7c478bd9Sstevel@tonic-gate proc_t *p = curproc; 60*7c478bd9Sstevel@tonic-gate long retval; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate switch (cmd) { 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate case UL_GFILLIM: /* Return current file size limit. */ 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate rlim64_t filesize; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 69*7c478bd9Sstevel@tonic-gate filesize = rctl_enforced_value(rctlproc_legacy[RLIMIT_FSIZE], 70*7c478bd9Sstevel@tonic-gate p->p_rctls, p); 71*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate if (get_udatamodel() == DATAMODEL_ILP32) { 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * File size is returned in blocks for ulimit. 76*7c478bd9Sstevel@tonic-gate * This function is deprecated and therefore LFS API 77*7c478bd9Sstevel@tonic-gate * didn't define the behaviour of ulimit. 78*7c478bd9Sstevel@tonic-gate * Here we return maximum value of file size possible 79*7c478bd9Sstevel@tonic-gate * so that applications that do not check errors 80*7c478bd9Sstevel@tonic-gate * continue to work. 81*7c478bd9Sstevel@tonic-gate */ 82*7c478bd9Sstevel@tonic-gate if (filesize > MAXOFF32_T) 83*7c478bd9Sstevel@tonic-gate filesize = MAXOFF32_T; 84*7c478bd9Sstevel@tonic-gate retval = ((int)filesize >> SCTRSHFT); 85*7c478bd9Sstevel@tonic-gate } else 86*7c478bd9Sstevel@tonic-gate retval = filesize >> SCTRSHFT; 87*7c478bd9Sstevel@tonic-gate break; 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate case UL_SFILLIM: /* Set new file size limit. */ 91*7c478bd9Sstevel@tonic-gate { 92*7c478bd9Sstevel@tonic-gate int error = 0; 93*7c478bd9Sstevel@tonic-gate rlim64_t lim = (rlim64_t)arg; 94*7c478bd9Sstevel@tonic-gate struct rlimit64 rl64; 95*7c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp = rctl_rlimit_set_prealloc(1); 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate if (lim >= (((rlim64_t)MAXOFFSET_T) >> SCTRSHFT)) 98*7c478bd9Sstevel@tonic-gate lim = (rlim64_t)RLIM64_INFINITY; 99*7c478bd9Sstevel@tonic-gate else 100*7c478bd9Sstevel@tonic-gate lim <<= SCTRSHFT; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate rl64.rlim_max = rl64.rlim_cur = lim; 103*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 104*7c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[RLIMIT_FSIZE], p, 105*7c478bd9Sstevel@tonic-gate &rl64, gp, RCTL_LOCAL_DENY | RCTL_LOCAL_SIGNAL, SIGXFSZ, 106*7c478bd9Sstevel@tonic-gate CRED())) { 107*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 108*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 109*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 112*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 113*7c478bd9Sstevel@tonic-gate retval = arg; 114*7c478bd9Sstevel@tonic-gate break; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate case UL_GMEMLIM: /* Return maximum possible break value. */ 118*7c478bd9Sstevel@tonic-gate { 119*7c478bd9Sstevel@tonic-gate struct seg *seg; 120*7c478bd9Sstevel@tonic-gate struct seg *nextseg; 121*7c478bd9Sstevel@tonic-gate struct as *as = p->p_as; 122*7c478bd9Sstevel@tonic-gate caddr_t brkend; 123*7c478bd9Sstevel@tonic-gate caddr_t brkbase; 124*7c478bd9Sstevel@tonic-gate size_t size; 125*7c478bd9Sstevel@tonic-gate rlim64_t size_ctl; 126*7c478bd9Sstevel@tonic-gate rlim64_t vmem_ctl; 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * Find the segment with a virtual address 130*7c478bd9Sstevel@tonic-gate * greater than the end of the current break. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate nextseg = NULL; 133*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 134*7c478bd9Sstevel@tonic-gate brkbase = (caddr_t)p->p_brkbase; 135*7c478bd9Sstevel@tonic-gate brkend = (caddr_t)p->p_brkbase + p->p_brksize; 136*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* 139*7c478bd9Sstevel@tonic-gate * Since we can't return less than the current break, 140*7c478bd9Sstevel@tonic-gate * initialize the return value to the current break 141*7c478bd9Sstevel@tonic-gate */ 142*7c478bd9Sstevel@tonic-gate retval = (long)brkend; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate AS_LOCK_ENTER(as, &as->a_lock, RW_READER); 145*7c478bd9Sstevel@tonic-gate for (seg = as_findseg(as, brkend, 0); seg != NULL; 146*7c478bd9Sstevel@tonic-gate seg = AS_SEGNEXT(as, seg)) { 147*7c478bd9Sstevel@tonic-gate if (seg->s_base >= brkend) { 148*7c478bd9Sstevel@tonic-gate nextseg = seg; 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 154*7c478bd9Sstevel@tonic-gate size_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_DATA], 155*7c478bd9Sstevel@tonic-gate p->p_rctls, p); 156*7c478bd9Sstevel@tonic-gate vmem_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_VMEM], 157*7c478bd9Sstevel@tonic-gate p->p_rctls, p); 158*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * First, calculate the maximum break value based on 162*7c478bd9Sstevel@tonic-gate * the user's RLIMIT_DATA, but also taking into account 163*7c478bd9Sstevel@tonic-gate * that this value cannot be greater than as->a_userlimit. 164*7c478bd9Sstevel@tonic-gate * We also take care to make sure that we don't overflow 165*7c478bd9Sstevel@tonic-gate * in the calculation. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate /* 168*7c478bd9Sstevel@tonic-gate * Since we are casting the RLIMIT_DATA value to a 169*7c478bd9Sstevel@tonic-gate * ulong (a 32-bit value in the 32-bit kernel) we have 170*7c478bd9Sstevel@tonic-gate * to pass this assertion. 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate ASSERT32((size_t)size_ctl <= UINT32_MAX); 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate size = (size_t)size_ctl; 175*7c478bd9Sstevel@tonic-gate if (as->a_userlimit - brkbase > size) 176*7c478bd9Sstevel@tonic-gate retval = MAX((size_t)retval, (size_t)(brkbase + size)); 177*7c478bd9Sstevel@tonic-gate /* don't return less than current */ 178*7c478bd9Sstevel@tonic-gate else 179*7c478bd9Sstevel@tonic-gate retval = (long)as->a_userlimit; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * The max break cannot extend into the next segment 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate if (nextseg != NULL) 185*7c478bd9Sstevel@tonic-gate retval = MIN((uintptr_t)retval, 186*7c478bd9Sstevel@tonic-gate (uintptr_t)nextseg->s_base); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * Handle the case where there is an limit on RLIMIT_VMEM 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate if (vmem_ctl < UINT64_MAX) { 192*7c478bd9Sstevel@tonic-gate /* calculate brkend based on the end of page */ 193*7c478bd9Sstevel@tonic-gate caddr_t brkendpg = (caddr_t)roundup((uintptr_t)brkend, 194*7c478bd9Sstevel@tonic-gate PAGESIZE); 195*7c478bd9Sstevel@tonic-gate /* 196*7c478bd9Sstevel@tonic-gate * Large Files: The following assertion has to pass 197*7c478bd9Sstevel@tonic-gate * through to ensure the correctness of the cast. 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate ASSERT32(vmem_ctl <= UINT32_MAX); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate size = (size_t)(vmem_ctl & PAGEMASK); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate if (as->a_size < size) 204*7c478bd9Sstevel@tonic-gate size -= as->a_size; 205*7c478bd9Sstevel@tonic-gate else 206*7c478bd9Sstevel@tonic-gate size = 0; 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * Take care to not overflow the calculation 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate if (as->a_userlimit - brkendpg > size) 211*7c478bd9Sstevel@tonic-gate retval = MIN((size_t)retval, 212*7c478bd9Sstevel@tonic-gate (size_t)(brkendpg + size)); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate AS_LOCK_EXIT(as, &as->a_lock); 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* truncate to same boundary as sbrk */ 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate switch (get_udatamodel()) { 220*7c478bd9Sstevel@tonic-gate default: 221*7c478bd9Sstevel@tonic-gate case DATAMODEL_ILP32: 222*7c478bd9Sstevel@tonic-gate retval = retval & ~(8-1); 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate case DATAMODEL_LP64: 225*7c478bd9Sstevel@tonic-gate retval = retval & ~(16-1); 226*7c478bd9Sstevel@tonic-gate break; 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate break; 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate case UL_GDESLIM: /* Return approximate number of open files */ 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate rlim64_t fdno_ctl; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate mutex_enter(&curproc->p_lock); 236*7c478bd9Sstevel@tonic-gate fdno_ctl = rctl_enforced_value(rctlproc_legacy[RLIMIT_NOFILE], 237*7c478bd9Sstevel@tonic-gate curproc->p_rctls, curproc); 238*7c478bd9Sstevel@tonic-gate ASSERT(fdno_ctl <= INT_MAX); 239*7c478bd9Sstevel@tonic-gate retval = (rlim_t)fdno_ctl; 240*7c478bd9Sstevel@tonic-gate mutex_exit(&curproc->p_lock); 241*7c478bd9Sstevel@tonic-gate break; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate default: 245*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate return (retval); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate int 254*7c478bd9Sstevel@tonic-gate ulimit32(int cmd, int arg) 255*7c478bd9Sstevel@tonic-gate { 256*7c478bd9Sstevel@tonic-gate return ((int)ulimit(cmd, (long)arg)); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL */ 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate #if defined(_ILP32) || defined(_SYSCALL32_IMPL) 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * Large Files: getrlimit returns RLIM_SAVED_CUR or RLIM_SAVED_MAX when 265*7c478bd9Sstevel@tonic-gate * rlim_cur or rlim_max is not representable in 32-bit rlim_t. These 266*7c478bd9Sstevel@tonic-gate * values are just tokens which will be used in setrlimit to set the 267*7c478bd9Sstevel@tonic-gate * correct limits. The current limits are saved in the saved_rlimit members 268*7c478bd9Sstevel@tonic-gate * in user structures when the token is returned. setrlimit restores 269*7c478bd9Sstevel@tonic-gate * the limit values to these saved values when the token is passed. 270*7c478bd9Sstevel@tonic-gate * Consider the following common scenario of the apps: 271*7c478bd9Sstevel@tonic-gate * 272*7c478bd9Sstevel@tonic-gate * limit = getrlimit(); 273*7c478bd9Sstevel@tonic-gate * savedlimit = limit; 274*7c478bd9Sstevel@tonic-gate * limit = limit1; 275*7c478bd9Sstevel@tonic-gate * setrlimit(limit) 276*7c478bd9Sstevel@tonic-gate * // execute all processes in the new rlimit state. 277*7c478bd9Sstevel@tonic-gate * setrlimit(savedlimit) // restore the old values. 278*7c478bd9Sstevel@tonic-gate * 279*7c478bd9Sstevel@tonic-gate * Most apps don't check error returns from getrlimit or setrlimit 280*7c478bd9Sstevel@tonic-gate * and this is why we return tokens when the correct value 281*7c478bd9Sstevel@tonic-gate * cannot be represented in rlim_t. For more discussion refer to 282*7c478bd9Sstevel@tonic-gate * the LFS API document. 283*7c478bd9Sstevel@tonic-gate * 284*7c478bd9Sstevel@tonic-gate * In the 64-bit kernel, all existing resource limits are treated in this 285*7c478bd9Sstevel@tonic-gate * manner. In the 32-bit kernel, CPU time is treated equivalently to the 286*7c478bd9Sstevel@tonic-gate * file size limit above; the VM-related limits are not. The macro, 287*7c478bd9Sstevel@tonic-gate * RLIM_SAVED(x), returns true if the resource limit should be handled in 288*7c478bd9Sstevel@tonic-gate * this way on the current kernel. 289*7c478bd9Sstevel@tonic-gate */ 290*7c478bd9Sstevel@tonic-gate int 291*7c478bd9Sstevel@tonic-gate getrlimit32(int resource, struct rlimit32 *rlp) 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate struct rlimit32 rlim32; 294*7c478bd9Sstevel@tonic-gate struct rlimit64 rlim64; 295*7c478bd9Sstevel@tonic-gate struct proc *p = curproc; 296*7c478bd9Sstevel@tonic-gate struct user *up = PTOU(p); 297*7c478bd9Sstevel@tonic-gate int savecur = 0; 298*7c478bd9Sstevel@tonic-gate int savemax = 0; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS) 301*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 304*7c478bd9Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[resource], p, &rlim64); 305*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate if (rlim64.rlim_max > (rlim64_t)UINT32_MAX) { 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate if (rlim64.rlim_max == RLIM64_INFINITY) 310*7c478bd9Sstevel@tonic-gate rlim32.rlim_max = RLIM32_INFINITY; 311*7c478bd9Sstevel@tonic-gate else { 312*7c478bd9Sstevel@tonic-gate savemax = 1; 313*7c478bd9Sstevel@tonic-gate rlim32.rlim_max = RLIM32_SAVED_MAX; 314*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 315*7c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource)); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if (rlim64.rlim_cur == RLIM64_INFINITY) 319*7c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_INFINITY; 320*7c478bd9Sstevel@tonic-gate else if (rlim64.rlim_cur == rlim64.rlim_max) { 321*7c478bd9Sstevel@tonic-gate savecur = 1; 322*7c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_SAVED_MAX; 323*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 324*7c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource)); 325*7c478bd9Sstevel@tonic-gate } else if (rlim64.rlim_cur > (rlim64_t)UINT32_MAX) { 326*7c478bd9Sstevel@tonic-gate savecur = 1; 327*7c478bd9Sstevel@tonic-gate rlim32.rlim_cur = RLIM32_SAVED_CUR; 328*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 329*7c478bd9Sstevel@tonic-gate ASSERT(RLIM_SAVED(resource)); 330*7c478bd9Sstevel@tonic-gate } else 331*7c478bd9Sstevel@tonic-gate rlim32.rlim_cur = rlim64.rlim_cur; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * save the current limits in user structure. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 337*7c478bd9Sstevel@tonic-gate if (RLIM_SAVED(resource)) { 338*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 339*7c478bd9Sstevel@tonic-gate if (savemax) 340*7c478bd9Sstevel@tonic-gate up->u_saved_rlimit[resource].rlim_max = 341*7c478bd9Sstevel@tonic-gate rlim64.rlim_max; 342*7c478bd9Sstevel@tonic-gate if (savecur) 343*7c478bd9Sstevel@tonic-gate up->u_saved_rlimit[resource].rlim_cur = 344*7c478bd9Sstevel@tonic-gate rlim64.rlim_cur; 345*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate } else { 348*7c478bd9Sstevel@tonic-gate ASSERT(rlim64.rlim_cur <= (rlim64_t)UINT32_MAX); 349*7c478bd9Sstevel@tonic-gate rlim32.rlim_max = rlim64.rlim_max; 350*7c478bd9Sstevel@tonic-gate rlim32.rlim_cur = rlim64.rlim_cur; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate if (copyout(&rlim32, rlp, sizeof (rlim32))) 354*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate return (0); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* 360*7c478bd9Sstevel@tonic-gate * See comments above getrlimit32(). When the tokens are passed in the 361*7c478bd9Sstevel@tonic-gate * rlimit structure the values are considered equal to the values 362*7c478bd9Sstevel@tonic-gate * stored in saved_rlimit members of user structure. 363*7c478bd9Sstevel@tonic-gate * When the user passes RLIM_INFINITY to set the resource limit to 364*7c478bd9Sstevel@tonic-gate * unlimited internally understand this value as RLIM64_INFINITY and 365*7c478bd9Sstevel@tonic-gate * let rlimit() do the job. 366*7c478bd9Sstevel@tonic-gate */ 367*7c478bd9Sstevel@tonic-gate int 368*7c478bd9Sstevel@tonic-gate setrlimit32(int resource, struct rlimit32 *rlp) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate struct rlimit32 rlim32; 371*7c478bd9Sstevel@tonic-gate struct rlimit64 rlim64; 372*7c478bd9Sstevel@tonic-gate struct rlimit64 saved_rlim; 373*7c478bd9Sstevel@tonic-gate int error; 374*7c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread); 375*7c478bd9Sstevel@tonic-gate struct user *up = PTOU(p); 376*7c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp; 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS) 379*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 380*7c478bd9Sstevel@tonic-gate if (copyin(rlp, &rlim32, sizeof (rlim32))) 381*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate gp = rctl_rlimit_set_prealloc(1); 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * Disallow resource limit tunnelling 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate /*CONSTCOND*/ 389*7c478bd9Sstevel@tonic-gate if (RLIM_SAVED(resource)) { 390*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 391*7c478bd9Sstevel@tonic-gate saved_rlim = up->u_saved_rlimit[resource]; 392*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 393*7c478bd9Sstevel@tonic-gate } else { 394*7c478bd9Sstevel@tonic-gate saved_rlim.rlim_max = (rlim64_t)rlim32.rlim_max; 395*7c478bd9Sstevel@tonic-gate saved_rlim.rlim_cur = (rlim64_t)rlim32.rlim_cur; 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate switch (rlim32.rlim_cur) { 399*7c478bd9Sstevel@tonic-gate case RLIM32_INFINITY: 400*7c478bd9Sstevel@tonic-gate rlim64.rlim_cur = RLIM64_INFINITY; 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate case RLIM32_SAVED_CUR: 403*7c478bd9Sstevel@tonic-gate rlim64.rlim_cur = saved_rlim.rlim_cur; 404*7c478bd9Sstevel@tonic-gate break; 405*7c478bd9Sstevel@tonic-gate case RLIM32_SAVED_MAX: 406*7c478bd9Sstevel@tonic-gate rlim64.rlim_cur = saved_rlim.rlim_max; 407*7c478bd9Sstevel@tonic-gate break; 408*7c478bd9Sstevel@tonic-gate default: 409*7c478bd9Sstevel@tonic-gate rlim64.rlim_cur = (rlim64_t)rlim32.rlim_cur; 410*7c478bd9Sstevel@tonic-gate break; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate switch (rlim32.rlim_max) { 414*7c478bd9Sstevel@tonic-gate case RLIM32_INFINITY: 415*7c478bd9Sstevel@tonic-gate rlim64.rlim_max = RLIM64_INFINITY; 416*7c478bd9Sstevel@tonic-gate break; 417*7c478bd9Sstevel@tonic-gate case RLIM32_SAVED_MAX: 418*7c478bd9Sstevel@tonic-gate rlim64.rlim_max = saved_rlim.rlim_max; 419*7c478bd9Sstevel@tonic-gate break; 420*7c478bd9Sstevel@tonic-gate case RLIM32_SAVED_CUR: 421*7c478bd9Sstevel@tonic-gate rlim64.rlim_max = saved_rlim.rlim_cur; 422*7c478bd9Sstevel@tonic-gate break; 423*7c478bd9Sstevel@tonic-gate default: 424*7c478bd9Sstevel@tonic-gate rlim64.rlim_max = (rlim64_t)rlim32.rlim_max; 425*7c478bd9Sstevel@tonic-gate break; 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 429*7c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[resource], p, &rlim64, gp, 430*7c478bd9Sstevel@tonic-gate rctlproc_flags[resource], rctlproc_signals[resource], CRED())) { 431*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 432*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 433*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 436*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 437*7c478bd9Sstevel@tonic-gate 438*7c478bd9Sstevel@tonic-gate return (0); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate #endif /* _ILP32 && _SYSCALL32_IMPL */ 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate int 444*7c478bd9Sstevel@tonic-gate getrlimit64(int resource, struct rlimit64 *rlp) 445*7c478bd9Sstevel@tonic-gate { 446*7c478bd9Sstevel@tonic-gate struct rlimit64 rlim64; 447*7c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS) 450*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 453*7c478bd9Sstevel@tonic-gate (void) rctl_rlimit_get(rctlproc_legacy[resource], p, &rlim64); 454*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (copyout(&rlim64, rlp, sizeof (rlim64))) 457*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 458*7c478bd9Sstevel@tonic-gate return (0); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate int 462*7c478bd9Sstevel@tonic-gate setrlimit64(int resource, struct rlimit64 *rlp) 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate struct rlimit64 rlim64; 465*7c478bd9Sstevel@tonic-gate struct proc *p = ttoproc(curthread); 466*7c478bd9Sstevel@tonic-gate int error; 467*7c478bd9Sstevel@tonic-gate rctl_alloc_gp_t *gp; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (resource < 0 || resource >= RLIM_NLIMITS) 470*7c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 471*7c478bd9Sstevel@tonic-gate if (copyin(rlp, &rlim64, sizeof (rlim64))) 472*7c478bd9Sstevel@tonic-gate return (set_errno(EFAULT)); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate gp = rctl_rlimit_set_prealloc(1); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 477*7c478bd9Sstevel@tonic-gate if (error = rctl_rlimit_set(rctlproc_legacy[resource], p, &rlim64, gp, 478*7c478bd9Sstevel@tonic-gate rctlproc_flags[resource], rctlproc_signals[resource], CRED())) { 479*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 480*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 481*7c478bd9Sstevel@tonic-gate return (set_errno(error)); 482*7c478bd9Sstevel@tonic-gate } 483*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 484*7c478bd9Sstevel@tonic-gate rctl_prealloc_destroy(gp); 485*7c478bd9Sstevel@tonic-gate return (0); 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate } 488