1*4afad4b7Schristos /* $NetBSD: resource.c,v 1.1 2024/02/18 20:57:57 christos Exp $ */
2*4afad4b7Schristos
3*4afad4b7Schristos /*
4*4afad4b7Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5*4afad4b7Schristos *
6*4afad4b7Schristos * SPDX-License-Identifier: MPL-2.0
7*4afad4b7Schristos *
8*4afad4b7Schristos * This Source Code Form is subject to the terms of the Mozilla Public
9*4afad4b7Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this
10*4afad4b7Schristos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11*4afad4b7Schristos *
12*4afad4b7Schristos * See the COPYRIGHT file distributed with this work for additional
13*4afad4b7Schristos * information regarding copyright ownership.
14*4afad4b7Schristos */
15*4afad4b7Schristos
16*4afad4b7Schristos #include <inttypes.h>
17*4afad4b7Schristos #include <stdbool.h>
18*4afad4b7Schristos #include <sys/resource.h>
19*4afad4b7Schristos #include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
20*4afad4b7Schristos #include <sys/types.h>
21*4afad4b7Schristos
22*4afad4b7Schristos #include <isc/platform.h>
23*4afad4b7Schristos #include <isc/resource.h>
24*4afad4b7Schristos #include <isc/result.h>
25*4afad4b7Schristos #include <isc/util.h>
26*4afad4b7Schristos
27*4afad4b7Schristos #ifdef __linux__
28*4afad4b7Schristos #include <linux/fs.h> /* To get the large NR_OPEN. */
29*4afad4b7Schristos #endif /* ifdef __linux__ */
30*4afad4b7Schristos
31*4afad4b7Schristos #include "errno2result.h"
32*4afad4b7Schristos
33*4afad4b7Schristos static isc_result_t
resource2rlim(isc_resource_t resource,int * rlim_resource)34*4afad4b7Schristos resource2rlim(isc_resource_t resource, int *rlim_resource) {
35*4afad4b7Schristos isc_result_t result = ISC_R_SUCCESS;
36*4afad4b7Schristos
37*4afad4b7Schristos switch (resource) {
38*4afad4b7Schristos case isc_resource_coresize:
39*4afad4b7Schristos *rlim_resource = RLIMIT_CORE;
40*4afad4b7Schristos break;
41*4afad4b7Schristos case isc_resource_cputime:
42*4afad4b7Schristos *rlim_resource = RLIMIT_CPU;
43*4afad4b7Schristos break;
44*4afad4b7Schristos case isc_resource_datasize:
45*4afad4b7Schristos *rlim_resource = RLIMIT_DATA;
46*4afad4b7Schristos break;
47*4afad4b7Schristos case isc_resource_filesize:
48*4afad4b7Schristos *rlim_resource = RLIMIT_FSIZE;
49*4afad4b7Schristos break;
50*4afad4b7Schristos case isc_resource_lockedmemory:
51*4afad4b7Schristos #ifdef RLIMIT_MEMLOCK
52*4afad4b7Schristos *rlim_resource = RLIMIT_MEMLOCK;
53*4afad4b7Schristos #else /* ifdef RLIMIT_MEMLOCK */
54*4afad4b7Schristos result = ISC_R_NOTIMPLEMENTED;
55*4afad4b7Schristos #endif /* ifdef RLIMIT_MEMLOCK */
56*4afad4b7Schristos break;
57*4afad4b7Schristos case isc_resource_openfiles:
58*4afad4b7Schristos #ifdef RLIMIT_NOFILE
59*4afad4b7Schristos *rlim_resource = RLIMIT_NOFILE;
60*4afad4b7Schristos #else /* ifdef RLIMIT_NOFILE */
61*4afad4b7Schristos result = ISC_R_NOTIMPLEMENTED;
62*4afad4b7Schristos #endif /* ifdef RLIMIT_NOFILE */
63*4afad4b7Schristos break;
64*4afad4b7Schristos case isc_resource_processes:
65*4afad4b7Schristos #ifdef RLIMIT_NPROC
66*4afad4b7Schristos *rlim_resource = RLIMIT_NPROC;
67*4afad4b7Schristos #else /* ifdef RLIMIT_NPROC */
68*4afad4b7Schristos result = ISC_R_NOTIMPLEMENTED;
69*4afad4b7Schristos #endif /* ifdef RLIMIT_NPROC */
70*4afad4b7Schristos break;
71*4afad4b7Schristos case isc_resource_residentsize:
72*4afad4b7Schristos #ifdef RLIMIT_RSS
73*4afad4b7Schristos *rlim_resource = RLIMIT_RSS;
74*4afad4b7Schristos #else /* ifdef RLIMIT_RSS */
75*4afad4b7Schristos result = ISC_R_NOTIMPLEMENTED;
76*4afad4b7Schristos #endif /* ifdef RLIMIT_RSS */
77*4afad4b7Schristos break;
78*4afad4b7Schristos case isc_resource_stacksize:
79*4afad4b7Schristos *rlim_resource = RLIMIT_STACK;
80*4afad4b7Schristos break;
81*4afad4b7Schristos default:
82*4afad4b7Schristos /*
83*4afad4b7Schristos * This test is not very robust if isc_resource_t
84*4afad4b7Schristos * changes, but generates a clear assertion message.
85*4afad4b7Schristos */
86*4afad4b7Schristos REQUIRE(resource >= isc_resource_coresize &&
87*4afad4b7Schristos resource <= isc_resource_stacksize);
88*4afad4b7Schristos
89*4afad4b7Schristos result = ISC_R_RANGE;
90*4afad4b7Schristos break;
91*4afad4b7Schristos }
92*4afad4b7Schristos
93*4afad4b7Schristos return (result);
94*4afad4b7Schristos }
95*4afad4b7Schristos
96*4afad4b7Schristos isc_result_t
isc_resource_setlimit(isc_resource_t resource,isc_resourcevalue_t value)97*4afad4b7Schristos isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
98*4afad4b7Schristos struct rlimit rl;
99*4afad4b7Schristos rlim_t rlim_value;
100*4afad4b7Schristos int unixresult;
101*4afad4b7Schristos int unixresource;
102*4afad4b7Schristos isc_result_t result;
103*4afad4b7Schristos
104*4afad4b7Schristos result = resource2rlim(resource, &unixresource);
105*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
106*4afad4b7Schristos return (result);
107*4afad4b7Schristos }
108*4afad4b7Schristos
109*4afad4b7Schristos if (value == ISC_RESOURCE_UNLIMITED) {
110*4afad4b7Schristos rlim_value = RLIM_INFINITY;
111*4afad4b7Schristos } else {
112*4afad4b7Schristos /*
113*4afad4b7Schristos * isc_resourcevalue_t was chosen as an unsigned 64 bit
114*4afad4b7Schristos * integer so that it could contain the maximum range of
115*4afad4b7Schristos * reasonable values. Unfortunately, this exceeds the typical
116*4afad4b7Schristos * range on Unix systems. Ensure the range of
117*4afad4b7Schristos * rlim_t is not overflowed.
118*4afad4b7Schristos */
119*4afad4b7Schristos isc_resourcevalue_t rlim_max;
120*4afad4b7Schristos bool rlim_t_is_signed = (((double)(rlim_t)-1) < 0);
121*4afad4b7Schristos
122*4afad4b7Schristos if (rlim_t_is_signed) {
123*4afad4b7Schristos rlim_max = ~((rlim_t)1 << (sizeof(rlim_t) * 8 - 1));
124*4afad4b7Schristos } else {
125*4afad4b7Schristos rlim_max = (rlim_t)-1;
126*4afad4b7Schristos }
127*4afad4b7Schristos
128*4afad4b7Schristos if (value > rlim_max) {
129*4afad4b7Schristos value = rlim_max;
130*4afad4b7Schristos }
131*4afad4b7Schristos
132*4afad4b7Schristos rlim_value = value;
133*4afad4b7Schristos }
134*4afad4b7Schristos
135*4afad4b7Schristos rl.rlim_cur = rl.rlim_max = rlim_value;
136*4afad4b7Schristos unixresult = setrlimit(unixresource, &rl);
137*4afad4b7Schristos
138*4afad4b7Schristos if (unixresult == 0) {
139*4afad4b7Schristos return (ISC_R_SUCCESS);
140*4afad4b7Schristos }
141*4afad4b7Schristos
142*4afad4b7Schristos #if defined(OPEN_MAX) && defined(__APPLE__)
143*4afad4b7Schristos /*
144*4afad4b7Schristos * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
145*4afad4b7Schristos * maximum possible value is OPEN_MAX. BIND8 used to use
146*4afad4b7Schristos * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
147*4afad4b7Schristos * smaller than OPEN_MAX and is not really effective.
148*4afad4b7Schristos */
149*4afad4b7Schristos if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
150*4afad4b7Schristos rl.rlim_cur = OPEN_MAX;
151*4afad4b7Schristos unixresult = setrlimit(unixresource, &rl);
152*4afad4b7Schristos if (unixresult == 0) {
153*4afad4b7Schristos return (ISC_R_SUCCESS);
154*4afad4b7Schristos }
155*4afad4b7Schristos }
156*4afad4b7Schristos #elif defined(__linux__)
157*4afad4b7Schristos #ifndef NR_OPEN
158*4afad4b7Schristos #define NR_OPEN (1024 * 1024)
159*4afad4b7Schristos #endif /* ifndef NR_OPEN */
160*4afad4b7Schristos
161*4afad4b7Schristos /*
162*4afad4b7Schristos * Some Linux kernels don't accept RLIM_INFINIT; the maximum
163*4afad4b7Schristos * possible value is the NR_OPEN defined in linux/fs.h.
164*4afad4b7Schristos */
165*4afad4b7Schristos if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
166*4afad4b7Schristos rl.rlim_cur = rl.rlim_max = NR_OPEN;
167*4afad4b7Schristos unixresult = setrlimit(unixresource, &rl);
168*4afad4b7Schristos if (unixresult == 0) {
169*4afad4b7Schristos return (ISC_R_SUCCESS);
170*4afad4b7Schristos }
171*4afad4b7Schristos }
172*4afad4b7Schristos #endif /* if defined(OPEN_MAX) && defined(__APPLE__) */
173*4afad4b7Schristos if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
174*4afad4b7Schristos if (getrlimit(unixresource, &rl) == 0) {
175*4afad4b7Schristos rl.rlim_cur = rl.rlim_max;
176*4afad4b7Schristos unixresult = setrlimit(unixresource, &rl);
177*4afad4b7Schristos if (unixresult == 0) {
178*4afad4b7Schristos return (ISC_R_SUCCESS);
179*4afad4b7Schristos }
180*4afad4b7Schristos }
181*4afad4b7Schristos }
182*4afad4b7Schristos return (isc__errno2result(errno));
183*4afad4b7Schristos }
184*4afad4b7Schristos
185*4afad4b7Schristos isc_result_t
isc_resource_getlimit(isc_resource_t resource,isc_resourcevalue_t * value)186*4afad4b7Schristos isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
187*4afad4b7Schristos int unixresource;
188*4afad4b7Schristos struct rlimit rl;
189*4afad4b7Schristos isc_result_t result;
190*4afad4b7Schristos
191*4afad4b7Schristos result = resource2rlim(resource, &unixresource);
192*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
193*4afad4b7Schristos return (result);
194*4afad4b7Schristos }
195*4afad4b7Schristos
196*4afad4b7Schristos if (getrlimit(unixresource, &rl) != 0) {
197*4afad4b7Schristos return (isc__errno2result(errno));
198*4afad4b7Schristos }
199*4afad4b7Schristos
200*4afad4b7Schristos *value = rl.rlim_max;
201*4afad4b7Schristos return (ISC_R_SUCCESS);
202*4afad4b7Schristos }
203*4afad4b7Schristos
204*4afad4b7Schristos isc_result_t
isc_resource_getcurlimit(isc_resource_t resource,isc_resourcevalue_t * value)205*4afad4b7Schristos isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
206*4afad4b7Schristos int unixresource;
207*4afad4b7Schristos struct rlimit rl;
208*4afad4b7Schristos isc_result_t result;
209*4afad4b7Schristos
210*4afad4b7Schristos result = resource2rlim(resource, &unixresource);
211*4afad4b7Schristos if (result != ISC_R_SUCCESS) {
212*4afad4b7Schristos return (result);
213*4afad4b7Schristos }
214*4afad4b7Schristos
215*4afad4b7Schristos if (getrlimit(unixresource, &rl) != 0) {
216*4afad4b7Schristos return (isc__errno2result(errno));
217*4afad4b7Schristos }
218*4afad4b7Schristos
219*4afad4b7Schristos *value = rl.rlim_cur;
220*4afad4b7Schristos return (ISC_R_SUCCESS);
221*4afad4b7Schristos }
222