xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/getrlimit/getrlimit03.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2018 Google, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  * Architectures may provide up to three syscalls that have been used to
6*49cdfc7eSAndroid Build Coastguard Worker  * implement getrlimit(2) in different libc implementations.  These syscalls
7*49cdfc7eSAndroid Build Coastguard Worker  * differ in the size and signedness of rlim_t:
8*49cdfc7eSAndroid Build Coastguard Worker  *
9*49cdfc7eSAndroid Build Coastguard Worker  * - __NR_getrlimit uses long or unsigned long, depending on the
10*49cdfc7eSAndroid Build Coastguard Worker  *   architecture
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * - __NR_ugetrlimit uses unsigned long, and only exists on
13*49cdfc7eSAndroid Build Coastguard Worker  *   architectures where __NR_getrlimit is signed
14*49cdfc7eSAndroid Build Coastguard Worker  *
15*49cdfc7eSAndroid Build Coastguard Worker  * - __NR_prlimit64 uses uint64_t
16*49cdfc7eSAndroid Build Coastguard Worker  *
17*49cdfc7eSAndroid Build Coastguard Worker  * This test compares the results returned by all three syscalls, confirming
18*49cdfc7eSAndroid Build Coastguard Worker  * that they either match or were appropriately capped at the respective
19*49cdfc7eSAndroid Build Coastguard Worker  * RLIM_INFINITY constant.
20*49cdfc7eSAndroid Build Coastguard Worker  */
21*49cdfc7eSAndroid Build Coastguard Worker 
22*49cdfc7eSAndroid Build Coastguard Worker #include <inttypes.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdint.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <sys/resource.h>
26*49cdfc7eSAndroid Build Coastguard Worker 
27*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
28*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/syscalls.h"
29*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/abisize.h"
30*49cdfc7eSAndroid Build Coastguard Worker 
31*49cdfc7eSAndroid Build Coastguard Worker /**
32*49cdfc7eSAndroid Build Coastguard Worker  * Linux provides an "old" getrlimit syscall handler that uses signed long,
33*49cdfc7eSAndroid Build Coastguard Worker  * and a "new" getrlimit syscall handler that uses unsigned long.
34*49cdfc7eSAndroid Build Coastguard Worker  *
35*49cdfc7eSAndroid Build Coastguard Worker  * The underlying syscall names vary across architectures, depending on whether
36*49cdfc7eSAndroid Build Coastguard Worker  * the architecture predates the "new" handler.  For clarity, this test
37*49cdfc7eSAndroid Build Coastguard Worker  * will call them getrlimit_long and getlimit_ulong internally.
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  * __NR_getrlimit has been deprecated from arm EABI and moved to OABI_COMPAT,
40*49cdfc7eSAndroid Build Coastguard Worker  * so the syscall on arm may or may not be available even if __NR_ugetrlimit
41*49cdfc7eSAndroid Build Coastguard Worker  * exists.
42*49cdfc7eSAndroid Build Coastguard Worker  */
43*49cdfc7eSAndroid Build Coastguard Worker #if __NR_ugetrlimit != __LTP__NR_INVALID_SYSCALL
44*49cdfc7eSAndroid Build Coastguard Worker # if !defined(__arm__) || __NR_getrlimit != __LTP__NR_INVALID_SYSCALL
45*49cdfc7eSAndroid Build Coastguard Worker #  define SIGNED_GETRLIMIT
46*49cdfc7eSAndroid Build Coastguard Worker # endif
47*49cdfc7eSAndroid Build Coastguard Worker # define __NR_getrlimit_ulong		__NR_ugetrlimit
48*49cdfc7eSAndroid Build Coastguard Worker # define __NR_getrlimit_ulong_str	"__NR_ugetrlimit"
49*49cdfc7eSAndroid Build Coastguard Worker #else
50*49cdfc7eSAndroid Build Coastguard Worker # define __NR_getrlimit_ulong		__NR_getrlimit
51*49cdfc7eSAndroid Build Coastguard Worker # define __NR_getrlimit_ulong_str	"__NR_getrlimit"
52*49cdfc7eSAndroid Build Coastguard Worker #endif
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker #ifndef HAVE_STRUCT_RLIMIT64
55*49cdfc7eSAndroid Build Coastguard Worker struct rlimit64 {
56*49cdfc7eSAndroid Build Coastguard Worker 	uint64_t rlim_cur;
57*49cdfc7eSAndroid Build Coastguard Worker 	uint64_t rlim_max;
58*49cdfc7eSAndroid Build Coastguard Worker };
59*49cdfc7eSAndroid Build Coastguard Worker #endif
60*49cdfc7eSAndroid Build Coastguard Worker const uint64_t RLIM_INFINITY_U64 = UINT64_MAX;
61*49cdfc7eSAndroid Build Coastguard Worker 
getrlimit_u64(int resource,struct rlimit64 * rlim)62*49cdfc7eSAndroid Build Coastguard Worker static int getrlimit_u64(int resource, struct rlimit64 *rlim)
63*49cdfc7eSAndroid Build Coastguard Worker {
64*49cdfc7eSAndroid Build Coastguard Worker 	return tst_syscall(__NR_prlimit64, 0, resource, NULL, rlim);
65*49cdfc7eSAndroid Build Coastguard Worker }
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker struct rlimit_ulong {
68*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long rlim_cur;
69*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long rlim_max;
70*49cdfc7eSAndroid Build Coastguard Worker };
71*49cdfc7eSAndroid Build Coastguard Worker 
72*49cdfc7eSAndroid Build Coastguard Worker #if defined(__mips__) && defined(TST_ABI32)
73*49cdfc7eSAndroid Build Coastguard Worker 	const unsigned long RLIM_INFINITY_UL = 0x7fffffffUL;
74*49cdfc7eSAndroid Build Coastguard Worker #else
75*49cdfc7eSAndroid Build Coastguard Worker 	const unsigned long RLIM_INFINITY_UL = ULONG_MAX;
76*49cdfc7eSAndroid Build Coastguard Worker #endif
77*49cdfc7eSAndroid Build Coastguard Worker 
getrlimit_ulong(int resource,struct rlimit_ulong * rlim)78*49cdfc7eSAndroid Build Coastguard Worker static int getrlimit_ulong(int resource, struct rlimit_ulong *rlim)
79*49cdfc7eSAndroid Build Coastguard Worker {
80*49cdfc7eSAndroid Build Coastguard Worker 	return syscall(__NR_getrlimit_ulong, resource, rlim);
81*49cdfc7eSAndroid Build Coastguard Worker }
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker const long RLIM_INFINITY_L = LONG_MAX;
84*49cdfc7eSAndroid Build Coastguard Worker 
85*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGNED_GETRLIMIT
86*49cdfc7eSAndroid Build Coastguard Worker struct rlimit_long {
87*49cdfc7eSAndroid Build Coastguard Worker 	long rlim_cur;
88*49cdfc7eSAndroid Build Coastguard Worker 	long rlim_max;
89*49cdfc7eSAndroid Build Coastguard Worker };
90*49cdfc7eSAndroid Build Coastguard Worker 
getrlimit_long(int resource,struct rlimit_long * rlim)91*49cdfc7eSAndroid Build Coastguard Worker static int getrlimit_long(int resource, struct rlimit_long *rlim)
92*49cdfc7eSAndroid Build Coastguard Worker {
93*49cdfc7eSAndroid Build Coastguard Worker 	return syscall(__NR_getrlimit, resource, rlim);
94*49cdfc7eSAndroid Build Coastguard Worker }
95*49cdfc7eSAndroid Build Coastguard Worker #endif
96*49cdfc7eSAndroid Build Coastguard Worker 
compare_retval(int resource,int ret_u64,int errno_u64,int ret_other,int errno_other,const char * other_syscall)97*49cdfc7eSAndroid Build Coastguard Worker static int compare_retval(int resource, int ret_u64, int errno_u64,
98*49cdfc7eSAndroid Build Coastguard Worker 			  int ret_other, int errno_other,
99*49cdfc7eSAndroid Build Coastguard Worker 			  const char *other_syscall)
100*49cdfc7eSAndroid Build Coastguard Worker {
101*49cdfc7eSAndroid Build Coastguard Worker 	if (ret_u64 != ret_other || errno_u64 != errno_other) {
102*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "__NR_prlimit64(%d) returned %d (%s) but %s(%d) returned %d (%s)",
103*49cdfc7eSAndroid Build Coastguard Worker 			resource, ret_u64, tst_strerrno(errno_u64),
104*49cdfc7eSAndroid Build Coastguard Worker 			other_syscall, resource, ret_other,
105*49cdfc7eSAndroid Build Coastguard Worker 			tst_strerrno(errno_other));
106*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
107*49cdfc7eSAndroid Build Coastguard Worker 	}
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
110*49cdfc7eSAndroid Build Coastguard Worker }
111*49cdfc7eSAndroid Build Coastguard Worker 
compare_u64_ulong(int resource,uint64_t val_u64,unsigned long val_ul,const char * kind)112*49cdfc7eSAndroid Build Coastguard Worker static int compare_u64_ulong(int resource, uint64_t val_u64,
113*49cdfc7eSAndroid Build Coastguard Worker 			     unsigned long val_ul, const char *kind)
114*49cdfc7eSAndroid Build Coastguard Worker {
115*49cdfc7eSAndroid Build Coastguard Worker 	if ((val_u64 > RLIM_INFINITY_UL && val_ul != RLIM_INFINITY_UL) ||
116*49cdfc7eSAndroid Build Coastguard Worker 	    (val_u64 <= RLIM_INFINITY_UL && val_ul != val_u64)) {
117*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "__NR_prlimit64(%d) had %s = %" PRIx64 " but " __NR_getrlimit_ulong_str "(%d) had %s = %lx",
118*49cdfc7eSAndroid Build Coastguard Worker 			resource, kind, val_u64,
119*49cdfc7eSAndroid Build Coastguard Worker 			resource, kind, val_ul);
120*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
121*49cdfc7eSAndroid Build Coastguard Worker 	}
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
124*49cdfc7eSAndroid Build Coastguard Worker }
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGNED_GETRLIMIT
compare_u64_long(int resource,uint64_t val_u64,long val_l,const char * kind)127*49cdfc7eSAndroid Build Coastguard Worker static int compare_u64_long(int resource, uint64_t val_u64, long val_l,
128*49cdfc7eSAndroid Build Coastguard Worker 			    const char *kind)
129*49cdfc7eSAndroid Build Coastguard Worker {
130*49cdfc7eSAndroid Build Coastguard Worker 	if ((val_u64 > (uint64_t)RLIM_INFINITY_L && val_l != RLIM_INFINITY_L) ||
131*49cdfc7eSAndroid Build Coastguard Worker 	    (val_u64 <= (uint64_t)RLIM_INFINITY_L && val_l != (long)val_u64)) {
132*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "__NR_prlimit64(%d) had %s = %" PRIx64 " but __NR_getrlimit(%d) had %s = %lx",
133*49cdfc7eSAndroid Build Coastguard Worker 			resource, kind, val_u64,
134*49cdfc7eSAndroid Build Coastguard Worker 			resource, kind, val_l);
135*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
136*49cdfc7eSAndroid Build Coastguard Worker 	}
137*49cdfc7eSAndroid Build Coastguard Worker 
138*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
139*49cdfc7eSAndroid Build Coastguard Worker }
140*49cdfc7eSAndroid Build Coastguard Worker #endif
141*49cdfc7eSAndroid Build Coastguard Worker 
run(unsigned int resource)142*49cdfc7eSAndroid Build Coastguard Worker static void run(unsigned int resource)
143*49cdfc7eSAndroid Build Coastguard Worker {
144*49cdfc7eSAndroid Build Coastguard Worker 	struct rlimit64 rlim_u64;
145*49cdfc7eSAndroid Build Coastguard Worker 	int ret_u64;
146*49cdfc7eSAndroid Build Coastguard Worker 	int errno_u64;
147*49cdfc7eSAndroid Build Coastguard Worker 
148*49cdfc7eSAndroid Build Coastguard Worker 	struct rlimit_ulong rlim_ul;
149*49cdfc7eSAndroid Build Coastguard Worker 	int ret_ul;
150*49cdfc7eSAndroid Build Coastguard Worker 	int errno_ul;
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGNED_GETRLIMIT
153*49cdfc7eSAndroid Build Coastguard Worker 	struct rlimit_long rlim_l;
154*49cdfc7eSAndroid Build Coastguard Worker 	int ret_l;
155*49cdfc7eSAndroid Build Coastguard Worker 	int errno_l;
156*49cdfc7eSAndroid Build Coastguard Worker #endif
157*49cdfc7eSAndroid Build Coastguard Worker 
158*49cdfc7eSAndroid Build Coastguard Worker 	errno = 0;
159*49cdfc7eSAndroid Build Coastguard Worker 	ret_u64 = getrlimit_u64(resource, &rlim_u64);
160*49cdfc7eSAndroid Build Coastguard Worker 	errno_u64 = errno;
161*49cdfc7eSAndroid Build Coastguard Worker 
162*49cdfc7eSAndroid Build Coastguard Worker 	errno = 0;
163*49cdfc7eSAndroid Build Coastguard Worker 	ret_ul = getrlimit_ulong(resource, &rlim_ul);
164*49cdfc7eSAndroid Build Coastguard Worker 	errno_ul = errno;
165*49cdfc7eSAndroid Build Coastguard Worker 
166*49cdfc7eSAndroid Build Coastguard Worker 	if (compare_retval(resource, ret_u64, errno_u64, ret_ul, errno_ul,
167*49cdfc7eSAndroid Build Coastguard Worker 			   __NR_getrlimit_ulong_str) ||
168*49cdfc7eSAndroid Build Coastguard Worker 	    compare_u64_ulong(resource, rlim_u64.rlim_cur, rlim_ul.rlim_cur,
169*49cdfc7eSAndroid Build Coastguard Worker 			      "rlim_cur") ||
170*49cdfc7eSAndroid Build Coastguard Worker 	    compare_u64_ulong(resource, rlim_u64.rlim_max, rlim_ul.rlim_max,
171*49cdfc7eSAndroid Build Coastguard Worker 			      "rlim_max"))
172*49cdfc7eSAndroid Build Coastguard Worker 		return;
173*49cdfc7eSAndroid Build Coastguard Worker 
174*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "__NR_prlimit64(%d) and %s(%d) gave consistent results",
175*49cdfc7eSAndroid Build Coastguard Worker 		resource, __NR_getrlimit_ulong_str, resource);
176*49cdfc7eSAndroid Build Coastguard Worker 
177*49cdfc7eSAndroid Build Coastguard Worker #ifdef SIGNED_GETRLIMIT
178*49cdfc7eSAndroid Build Coastguard Worker 	errno = 0;
179*49cdfc7eSAndroid Build Coastguard Worker 	ret_l = getrlimit_long(resource, &rlim_l);
180*49cdfc7eSAndroid Build Coastguard Worker 	errno_l = errno;
181*49cdfc7eSAndroid Build Coastguard Worker 	if (errno_l == ENOSYS) {
182*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TCONF | TERRNO,
183*49cdfc7eSAndroid Build Coastguard Worker 			"__NR_getrlimit(%d) not implemented", __NR_getrlimit);
184*49cdfc7eSAndroid Build Coastguard Worker 		return;
185*49cdfc7eSAndroid Build Coastguard Worker 	}
186*49cdfc7eSAndroid Build Coastguard Worker 
187*49cdfc7eSAndroid Build Coastguard Worker 	if (compare_retval(resource, ret_u64, errno_u64, ret_l, errno_l,
188*49cdfc7eSAndroid Build Coastguard Worker 			   "__NR_getrlimit") ||
189*49cdfc7eSAndroid Build Coastguard Worker 	    compare_u64_long(resource, rlim_u64.rlim_cur, rlim_l.rlim_cur,
190*49cdfc7eSAndroid Build Coastguard Worker 			     "rlim_cur") ||
191*49cdfc7eSAndroid Build Coastguard Worker 	    compare_u64_long(resource, rlim_u64.rlim_max, rlim_l.rlim_max,
192*49cdfc7eSAndroid Build Coastguard Worker 			     "rlim_max"))
193*49cdfc7eSAndroid Build Coastguard Worker 		return;
194*49cdfc7eSAndroid Build Coastguard Worker 
195*49cdfc7eSAndroid Build Coastguard Worker 	tst_res(TPASS, "__NR_prlimit64(%d) and __NR_getrlimit(%d) gave "
196*49cdfc7eSAndroid Build Coastguard Worker 		"consistent results", resource, resource);
197*49cdfc7eSAndroid Build Coastguard Worker #endif
198*49cdfc7eSAndroid Build Coastguard Worker }
199*49cdfc7eSAndroid Build Coastguard Worker 
200*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
201*49cdfc7eSAndroid Build Coastguard Worker 	.tcnt = RLIM_NLIMITS,
202*49cdfc7eSAndroid Build Coastguard Worker 	.test = run,
203*49cdfc7eSAndroid Build Coastguard Worker };
204