xref: /netbsd-src/external/mpl/dhcp/bind/dist/lib/isc/unix/resource.c (revision 4afad4b7fa6d4a0d3dedf41d1587a7250710ae54)
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