1 /*
2  * Copyright (C) 2014-2021 Canonical, Ltd.
3  * Copyright (C)      2021 Colin Ian King
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  */
20 #include "stress-ng.h"
21 
22 /*
23  *  Various shim abstraction wrappers around systems calls and
24  *  GCC helper functions that may not be supported by some
25  *  kernels or versions of different C libraries.
26  */
27 
28 /*
29  *  shim_enosys()
30  *	simulate unimplemented system call. Ignores
31  *	the sysnr argument and all following 1..N syscall
32  *	arguments.  Returns -1 and sets errno to ENOSYS
33  */
shim_enosys(long sysnr,...)34 static inline long shim_enosys(long sysnr, ...)
35 {
36 	(void)sysnr;
37 	errno = ENOSYS;
38 	return (long)-1;
39 }
40 
41 /*
42  *  shim_sched_yield()
43  *  	wrapper for sched_yield(2) - yield the processor
44  */
shim_sched_yield(void)45 int shim_sched_yield(void)
46 {
47 #if defined(HAVE_SCHED_YIELD)
48 	return sched_yield();
49 #elif defined(__NR_sched_yield)
50 	return syscall(__NR_sched_yield);
51 #else
52 	return sleep(0);
53 #endif
54 }
55 
56 /*
57  *  shim_cacheflush()
58  *	wrapper for cacheflush(2), flush contents of
59  *	instruction and/or data cache
60  */
shim_cacheflush(char * addr,int nbytes,int cache)61 int shim_cacheflush(char *addr, int nbytes, int cache)
62 {
63 #if defined(__NR_cacheflush)
64 	return (int)syscall(__NR_cacheflush, addr, nbytes, cache);
65 #else
66 	return (int)shim_enosys(0, addr, nbytes, cache);
67 #endif
68 }
69 
70 /*
71  * shim_copy_file_range()
72  *	wrapper for copy_file_range(2), copy range of data
73  *	from one file to another
74  */
shim_copy_file_range(int fd_in,shim_loff_t * off_in,int fd_out,shim_loff_t * off_out,size_t len,unsigned int flags)75 ssize_t shim_copy_file_range(
76 	int fd_in,
77 	shim_loff_t *off_in,
78 	int fd_out,
79 	shim_loff_t *off_out,
80 	size_t len,
81 	unsigned int flags)
82 {
83 #if defined(HAVE_COPY_FILE_RANGE)
84 	return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags);
85 #elif defined(__NR_copy_file_range)
86 	return (ssize_t)syscall(__NR_copy_file_range,
87 		fd_in, off_in, fd_out, off_out, len, flags);
88 #else
89 	return (ssize_t)shim_enosys(0, fd_in, off_in, fd_out, off_out, len, flags);
90 #endif
91 }
92 
93 /*
94  * shim_emulate_fallocate()
95  *	emulate fallocate (very slow!)
96  */
shim_emulate_fallocate(int fd,off_t offset,off_t len)97 static int shim_emulate_fallocate(int fd, off_t offset, off_t len)
98 {
99 	const off_t buf_sz = 8192;
100 	char buffer[buf_sz];
101 	off_t n;
102 
103 	n = lseek(fd, offset, SEEK_SET);
104 	if (n == (off_t)-1)
105 		return -1;
106 
107 	(void)memset(buffer, 0, buf_sz);
108 	n = len;
109 
110 	while (keep_stressing_flag() && (n > 0)) {
111 		ssize_t ret;
112 		size_t count = (size_t)STRESS_MINIMUM(n, buf_sz);
113 
114 		ret = write(fd, buffer, count);
115 		if (ret >= 0) {
116 			n -= ret;
117 		} else {
118 			return -1;
119 		}
120 	}
121 	return 0;
122 }
123 
124 /*
125  * shim_fallocate()
126  *	shim wrapper for fallocate system call
127  *	- falls back to posix_fallocate w/o mode
128  * 	- falls back to direct writes
129  */
shim_fallocate(int fd,int mode,off_t offset,off_t len)130 int shim_fallocate(int fd, int mode, off_t offset, off_t len)
131 {
132 #if defined(HAVE_FALLOCATE)
133 	int ret;
134 
135 	ret = fallocate(fd, mode, offset, len);
136 	/* mode not supported? try with zero mode (dirty hack) */
137 	if ((ret < 0) && (errno == EOPNOTSUPP)) {
138 		ret = (int)syscall(__NR_fallocate, fd, 0, offset, len);
139 		/* fallocate failed, try emulation mode */
140 		if ((ret < 0) && (errno == EOPNOTSUPP)) {
141 			ret = shim_emulate_fallocate(fd, offset, len);
142 		}
143 	}
144 	return ret;
145 #elif defined(__NR_fallocate)
146 	int ret;
147 
148 	ret = syscall(__NR_fallocate, fd, mode, offset, len);
149 	/* mode not supported? try with zero mode (dirty hack) */
150 	if ((ret < 0) && (errno == EOPNOTSUPP)) {
151 		ret = syscall(__NR_fallocate, fd, 0, offset, len);
152 		/* fallocate failed, try emulation mode */
153 		if ((ret < 0) && (errno == EOPNOTSUPP)) {
154 			ret = shim_emulate_fallocate(fd, offset, len);
155 		}
156 	}
157 	return ret;
158 #elif defined(HAVE_POSIX_FALLOCATE) &&	\
159       !defined(__FreeBSD_kernel__)
160 	/*
161 	 *  Even though FreeBSD kernels support this, large
162 	 *  allocations take forever to be interrupted and so
163 	 *  we don't use this for FreeBSD for now.
164 	 */
165 	int ret;
166 
167 	(void)mode;
168 
169 	/*
170 	 *  posix_fallocate returns 0 for success, > 0 as errno
171 	 */
172 	ret = posix_fallocate(fd, offset, len);
173 	errno = 0;
174 	if (ret != 0) {
175 		/* failed, so retry with slower emulated fallocate */
176 		ret = shim_emulate_fallocate(fd, offset, len);
177 	}
178 	return ret;
179 #else
180 	(void)mode;
181 
182 	return shim_emulate_fallocate(fd, offset, len);
183 #endif
184 }
185 
186 /*
187  *  shim_gettid()
188  *	wrapper for gettid(2), get thread identification
189  */
shim_gettid(void)190 int shim_gettid(void)
191 {
192 #if defined(__NR_gettid)
193 	return (int)syscall(__NR_gettid);
194 #else
195 	return (int)shim_enosys(0);
196 #endif
197 }
198 
199 /*
200  *  shim_getcpu()
201  *	wrapper for getcpu(2) - get CPU and NUMA node of
202  *	calling thread
203  */
shim_getcpu(unsigned * cpu,unsigned * node,void * tcache)204 long shim_getcpu(
205 	unsigned *cpu,
206 	unsigned *node,
207 	void *tcache)
208 {
209 #if defined(__NR_getcpu)
210 	return (long)syscall(__NR_getcpu, cpu, node, tcache);
211 #else
212 	return (long)shim_enosys(0, cpu, node, tcache);
213 #endif
214 }
215 
216 /*
217  *  shim_getdents()
218  *	wrapper for getdents(2) - get directory entries
219  */
shim_getdents(unsigned int fd,struct shim_linux_dirent * dirp,unsigned int count)220 int shim_getdents(
221 	unsigned int fd,
222 	struct shim_linux_dirent *dirp,
223 	unsigned int count)
224 {
225 #if defined(__NR_getdents)
226 	return (int)syscall(__NR_getdents, fd, dirp, count);
227 #else
228 	return (int)shim_enosys(0, fd, dirp, count);
229 #endif
230 }
231 
232 /*
233  *  shim_getdent64()
234  *	wrapper for getdents64(2) - get directory entries
235  */
shim_getdents64(unsigned int fd,struct shim_linux_dirent64 * dirp,unsigned int count)236 int shim_getdents64(
237 	unsigned int fd,
238 	struct shim_linux_dirent64 *dirp,
239 	unsigned int count)
240 {
241 #if defined(__NR_getdents64)
242 	return (int)syscall(__NR_getdents64, fd, dirp, count);
243 #else
244 	return (int)shim_enosys(0, fd, dirp, count);
245 #endif
246 }
247 
248 /*
249  *  shim_getrandom()
250  *	wrapper for Linux getrandom(2) and BSD getentropy(2)
251  */
shim_getrandom(void * buff,size_t buflen,unsigned int flags)252 int shim_getrandom(void *buff, size_t buflen, unsigned int flags)
253 {
254 #if defined(__NR_getrandom)
255 	return (int)syscall(__NR_getrandom, buff, buflen, flags);
256 #elif defined(__OpenBSD__) || defined(__APPLE__)
257 	(void)flags;
258 
259 	return getentropy(buff, buflen);
260 #else
261 	return (int)shim_enosys(0, buff, buflen, flags);
262 #endif
263 }
264 
265 /*
266  *  shim_flush_icache()
267  *	wrapper for RISC-V icache flush and ARM __clear_cache gcc intrinsic
268  */
shim_flush_icache(void * begin,void * end)269 void shim_flush_icache(void *begin, void *end)
270 {
271 #if defined(__GNUC__) &&	\
272     defined(STRESS_ARCH_ARM)
273 	__clear_cache(begin, end);
274 #elif defined(STRESS_ARCH_RISCV) &&	\
275       defined(__NR_riscv_flush_icache)
276 	(void)syscall(__NR_riscv_flush_icache, begin, end, 0);
277 #else
278 	(void)shim_enosys(0, begin, end);
279 #endif
280 }
281 
282 /*
283  *  shim_kcmp()
284  *	wrapper for Linux kcmp(2) - compare two processes to
285  *	see if they share a kernel resource.
286  */
shim_kcmp(pid_t pid1,pid_t pid2,int type,unsigned long idx1,unsigned long idx2)287 long shim_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2)
288 {
289 #if defined(__NR_kcmp)
290 	errno = 0;
291 	return (long)syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
292 #else
293 	return (long)shim_enosys(0, pid1, pid2, type, idx1, idx2);
294 #endif
295 }
296 
297 /*
298  *  shim_klogctl()
299  *	wrapper for syslog(2) (NOT syslog(3))
300  */
shim_klogctl(int type,char * bufp,int len)301 int shim_klogctl(int type, char *bufp, int len)
302 {
303 #if defined(__NR_syslog)
304 	return (int)syscall(__NR_syslog, type, bufp, len);
305 #else
306 	return (int)shim_enosys(0, type, bufp, len);
307 #endif
308 }
309 
310 /*
311  *  shim_membarrier()
312  *	wrapper for membarrier(2) - issue memory barriers
313  */
shim_membarrier(int cmd,int flags,int cpu_id)314 int shim_membarrier(int cmd, int flags, int cpu_id)
315 {
316 #if defined(__NR_membarrier)
317 	return (int)syscall(__NR_membarrier, cmd, flags, cpu_id);
318 #else
319 	return (int)shim_enosys(0, cmd, flags, cpu_id);
320 #endif
321 }
322 
323 /*
324  *  shim_memfd_create()
325  *	wrapper for memfd_create(2)
326  */
shim_memfd_create(const char * name,unsigned int flags)327 int shim_memfd_create(const char *name, unsigned int flags)
328 {
329 #if defined(__NR_memfd_create)
330 	return (int)syscall(__NR_memfd_create, name, flags);
331 #else
332 	return (int)shim_enosys(0, name, flags);
333 #endif
334 }
335 
336 /*
337  *  shim_get_mempolicy()
338  *	wrapper for get_mempolicy(2) - get NUMA memory policy
339  */
shim_get_mempolicy(int * mode,unsigned long * nodemask,unsigned long maxnode,void * addr,unsigned long flags)340 int shim_get_mempolicy(
341 	int *mode,
342 	unsigned long *nodemask,
343 	unsigned long maxnode,
344 	void *addr,
345 	unsigned long flags)
346 {
347 #if defined(__NR_get_mempolicy)
348 	return (int)syscall(__NR_get_mempolicy,
349 		mode, nodemask, maxnode, addr, flags);
350 #else
351 	return (int)shim_enosys(0, mode, nodemask, maxnode, addr, flags);
352 #endif
353 }
354 
355 /*
356  *  shim_set_mempolicy()
357  *	wrapper for set_mempolicy(2) - set NUMA memory policy
358  */
shim_set_mempolicy(int mode,unsigned long * nodemask,unsigned long maxnode)359 int shim_set_mempolicy(
360 	int mode,
361 	unsigned long *nodemask,
362 	unsigned long maxnode)
363 {
364 #if defined(__NR_set_mempolicy)
365 	return (int)syscall(__NR_set_mempolicy,
366 		mode, nodemask, maxnode);
367 #else
368 	return (int)shim_enosys(0, mode, nodemask, maxnode);
369 #endif
370 }
371 
372 /*
373  *  shim_mbind()
374  *	wrapper for mbind(2) - set memory policy for a memory range
375  */
shim_mbind(void * addr,unsigned long len,int mode,const unsigned long * nodemask,unsigned long maxnode,unsigned flags)376 long shim_mbind(
377 	void *addr,
378 	unsigned long len,
379 	int mode,
380 	const unsigned long *nodemask,
381 	unsigned long maxnode,
382 	unsigned flags)
383 {
384 #if defined(__NR_mbind)
385 	return (long)syscall(__NR_mbind,
386 		addr, len, mode, nodemask, maxnode, flags);
387 #else
388 	return (long)shim_enosys(0, addr, len, mode, nodemask, maxnode, flags);
389 #endif
390 }
391 
392 /*
393  *  shim_migrate_pages()
394  *	wrapper for migrate_pages(2) - move all pages in a process to other nodes
395  */
shim_migrate_pages(int pid,unsigned long maxnode,const unsigned long * old_nodes,const unsigned long * new_nodes)396 long shim_migrate_pages(
397 	int pid,
398 	unsigned long maxnode,
399 	const unsigned long *old_nodes,
400 	const unsigned long *new_nodes)
401 {
402 #if defined(__NR_migrate_pages)
403 	return (long)syscall(__NR_migrate_pages,
404 		pid, maxnode, old_nodes, new_nodes);
405 #else
406 	return (long)shim_enosys(0, pid, maxnode, old_nodes, new_nodes);
407 #endif
408 }
409 
410 /*
411  *  shim_move_pages()
412  *	wrapper for move_pages(2) - move pages in a process to other nodes
413  */
shim_move_pages(int pid,unsigned long count,void ** pages,const int * nodes,int * status,int flags)414 long shim_move_pages(
415 	int pid,
416 	unsigned long count,
417 	void **pages,
418 	const int *nodes,
419 	int *status,
420 	int flags)
421 {
422 #if defined(__NR_move_pages)
423 	return (long)syscall(__NR_move_pages, pid, count, pages, nodes,
424 		status, flags);
425 #else
426 	return (long)shim_enosys(0, pid, count, pages, nodes, status, flags);
427 #endif
428 }
429 
430 /*
431  *  shim_userfaultfd()
432  *	wrapper for userfaultfd(2)
433  */
shim_userfaultfd(int flags)434 int shim_userfaultfd(int flags)
435 {
436 #if defined(__NR_userfaultfd)
437 	return (int)syscall(__NR_userfaultfd, flags);
438 #else
439 	return (int)shim_enosys(0, flags);
440 #endif
441 }
442 
443 /*
444  *  shim_seccomp()
445  *	wrapper for seccomp(2) - operate on Secure Computing state of process
446  */
shim_seccomp(unsigned int operation,unsigned int flags,void * args)447 int shim_seccomp(unsigned int operation, unsigned int flags, void *args)
448 {
449 #if defined(__NR_seccomp)
450 	return (int)syscall(__NR_seccomp, operation, flags, args);
451 #else
452 	return (int)shim_enosys(0, operation, flags, args);
453 #endif
454 }
455 
456 /*
457  *  shim_unshare()
458  *	wrapper for unshare(2)
459  */
shim_unshare(int flags)460 int shim_unshare(int flags)
461 {
462 #if defined(__NR_unshare)
463 #if NEED_GLIBC(2,14,0)
464 	return unshare(flags);
465 #else
466 	return (int)syscall(__NR_unshare, flags);
467 #endif
468 #else
469 	return (int)shim_enosys(0, flags);
470 #endif
471 }
472 
473 /*
474  *  shim_shed_getattr()
475  *	wrapper for shed_getattr(2)
476  */
shim_sched_getattr(pid_t pid,struct shim_sched_attr * attr,unsigned int size,unsigned int flags)477 int shim_sched_getattr(
478 	pid_t pid,
479 	struct shim_sched_attr *attr,
480 	unsigned int size,
481 	unsigned int flags)
482 {
483 #if defined(__NR_sched_getattr)
484 	return (int)syscall(__NR_sched_getattr, pid, attr, size, flags);
485 #else
486 	return (int)shim_enosys(0, pid, attr, size, flags);
487 #endif
488 }
489 
490 /*
491  *  shim_shed_setattr()
492  *	wrapper for shed_setattr(2)
493  */
shim_sched_setattr(pid_t pid,struct shim_sched_attr * attr,unsigned int flags)494 int shim_sched_setattr(
495 	pid_t pid,
496 	struct shim_sched_attr *attr,
497 	unsigned int flags)
498 {
499 #if defined(__NR_sched_setattr)
500 	return (int)syscall(__NR_sched_setattr, pid, attr, flags);
501 #else
502 	return (int)shim_enosys(0, pid, attr, flags);
503 #endif
504 }
505 
506 /*
507  *  shim_mlock()
508  *	wrapper for mlock(2) - lock memory
509  */
shim_mlock(const void * addr,size_t len)510 int shim_mlock(const void *addr, size_t len)
511 {
512 #if defined(HAVE_MLOCK)
513 	return mlock(shim_unconstify_ptr(addr), len);
514 #elif defined(__NR_mlock)
515 	return (int)syscall(__NR_mlock, addr, len);
516 #else
517 	return (int)shim_enosys(0, addr, len);
518 #endif
519 }
520 
521 /*
522  *  shim_munlock()
523  *	wrapper for munlock(2) - unlock memory
524  */
shim_munlock(const void * addr,size_t len)525 int shim_munlock(const void *addr, size_t len)
526 {
527 #if defined(HAVE_MUNLOCK)
528 	return munlock(shim_unconstify_ptr(addr), len);
529 #elif defined(__NR_munlock)
530 	return (int)syscall(__NR_munlock, addr, len);
531 #else
532 	return (int)shim_enosys(0, addr, len);
533 #endif
534 }
535 
536 /*
537  *  shim_mlock2()
538  *	wrapper for mlock2(2) - lock memory
539  */
shim_mlock2(const void * addr,size_t len,int flags)540 int shim_mlock2(const void *addr, size_t len, int flags)
541 {
542 #if defined(__NR_mlock2)
543 	return (int)syscall(__NR_mlock2, addr, len, flags);
544 #else
545 	return (int)shim_enosys(0, addr, len, flags);
546 #endif
547 }
548 
549 /*
550  *  shim_mlockall()
551  * 	wrapper for mlockall() - lock all memory
552  */
shim_mlockall(int flags)553 int shim_mlockall(int flags)
554 {
555 #if defined(HAVE_MLOCKALL)
556 	return mlockall(flags);
557 #elif defined(__NR_mlockall)
558 	return (int)syscall(__NR_mlockall, flags);
559 #else
560 	return (int)shim_enosys(0, flags);
561 #endif
562 }
563 
564 /*
565  *  shim_munlockall()
566  * 	wrapper for munlockall() - unlock all memory
567  */
shim_munlockall(void)568 int shim_munlockall(void)
569 {
570 #if defined(HAVE_MUNLOCKALL)
571 	return munlockall();
572 #elif defined(__NR_munlockall)
573 	return (int)syscall(__NR_munlockall);
574 #else
575 	return (int)shim_enosys(0);
576 #endif
577 }
578 
579 /*
580  *  shim_nanosleep_uint64()
581  *	nanosecond sleep that handles being interrupted but will
582  *	be preempted if an ALARM signal has triggered a termination
583  */
shim_nanosleep_uint64(uint64_t nsec)584 int shim_nanosleep_uint64(uint64_t nsec)
585 {
586 #if defined(HAVE_NANOSLEEP)
587 	struct timespec t, trem;
588 
589 	t.tv_sec = nsec / STRESS_NANOSECOND;
590 	t.tv_nsec = nsec % STRESS_NANOSECOND;
591 
592 	for (;;) {
593 		errno = 0;
594 		if (nanosleep(&t, &trem) < 0) {
595 			if (errno == EINTR) {
596 				t = trem;
597 				if (keep_stressing_flag())
598 					continue;
599 			} else {
600 				return -1;
601 			}
602 		}
603 		break;
604 	}
605 #else
606 	useconds_t usec = nsec / 1000;
607 	const double t_end = stress_time_now() + (((double)usec) * ONE_MILLIONTH);
608 
609 	for (;;) {
610 		errno = 0;
611 		if (usleep(usec) < 0) {
612 			if (errno == EINTR) {
613 				double t_left = t_end - stress_time_now();
614 
615 				if (t_left < 0.0)
616 					return 0;
617 				usec = (useconds_t)(t_left * 1000000.0);
618 				if (usec == 0)
619 					return 0;
620 				if (keep_stressing_flag())
621 					continue;
622 			} else {
623 				return -1;
624 			}
625 		}
626 		break;
627 	}
628 #endif
629 	return 0;
630 }
631 
632 /*
633  *  shim_usleep()
634  *	usleep is now deprecated, so
635  *	emulate it with nanosleep
636  */
shim_usleep(uint64_t usec)637 int shim_usleep(uint64_t usec)
638 {
639 	return shim_nanosleep_uint64(usec * 1000);
640 }
641 
642 /*
643  *  shim_usleep_interruptible()
644  *	interruptible usleep
645  */
shim_usleep_interruptible(uint64_t usec)646 int shim_usleep_interruptible(uint64_t usec)
647 {
648 #if defined(HAVE_NANOSLEEP)
649 	struct timespec t, trem;
650 
651 	t.tv_sec = usec * ONE_MILLIONTH;
652 	t.tv_nsec = ((long int)usec - (t.tv_sec * 1000000)) * 1000;
653 
654 	errno = 0;
655 	return nanosleep(&t, &trem);
656 #else
657 	return usleep((useconds_t)usec);
658 #endif
659 }
660 
661 
662 /*
663  *  shim_getlogin
664  *	a more secure abstracted version of getlogin
665  *
666  * According to flawfinder:
667  * "It's often easy to fool getlogin. Sometimes it does not work at all,
668  * because some program messed up the utmp file. Often, it gives only the
669  * first 8 characters of the login name. The user currently logged in on the
670  * controlling tty of our program need not be the user who started it. Avoid
671  * getlogin() for security-related purposes (CWE-807). Use getpwuid(geteuid())
672  * and extract the desired information instead."
673  */
shim_getlogin(void)674 char *shim_getlogin(void)
675 {
676 #if defined(BUILD_STATIC)
677 	/*
678 	 *  static builds can't use getpwuid because of
679 	 *  dynamic linking issues. Ugh.
680 	 */
681 	return NULL;
682 #else
683 	static char pw_name[256];
684 	const struct passwd *pw = getpwuid(geteuid());
685 	if (!pw)
686 		return NULL;
687 
688 	(void)shim_strlcpy(pw_name, pw->pw_name, sizeof(pw_name));
689 	pw_name[sizeof(pw_name) - 1 ] = '\0';
690 
691 	return pw_name;
692 #endif
693 }
694 
695 /*
696  *  shim_msync()
697  *	wrapper for msync(2) - synchronize a file with a memory map
698  */
shim_msync(void * addr,size_t length,int flags)699 int shim_msync(void *addr, size_t length, int flags)
700 {
701 #if defined(HAVE_MSYNC)
702 	return msync(addr, length, flags);
703 #elif defined(__NR_msync)
704 	return (int)syscall(__NR_msync, addr, length, flags);
705 #else
706 	return (int)shim_enosys(0, addr, length, flags);
707 #endif
708 }
709 
710 /*
711  *  shim_sysfs()
712  *	wrapper for sysfs(2) - get filesystem type information
713  */
shim_sysfs(int option,...)714 int shim_sysfs(int option, ...)
715 {
716 #if defined(__NR_sysfs)
717 	int ret;
718 	va_list ap;
719 	char *fsname;
720 	unsigned int fs_index;
721 	char *buf;
722 
723 	va_start(ap, option);
724 
725 	switch (option) {
726 	case 1:
727 		fsname = va_arg(ap, char *);
728 		ret = (int)syscall(__NR_sysfs, option, fsname);
729 		break;
730 	case 2:
731 		fs_index = va_arg(ap, unsigned int);
732 		buf = va_arg(ap, char *);
733 		ret = (int)syscall(__NR_sysfs, option, fs_index, buf);
734 		break;
735 	case 3:
736 		ret = (int)syscall(__NR_sysfs, option);
737 		break;
738 	default:
739 		ret = -1;
740 		errno = EINVAL;
741 	}
742 
743 	va_end(ap);
744 
745 	return ret;
746 #else
747 	return (int)shim_enosys(0, option);
748 #endif
749 }
750 
751 /*
752  *  shim_madvise()
753  *	wrapper for madvise(2) - get filesystem type information
754  */
shim_madvise(void * addr,size_t length,int advice)755 int shim_madvise(void *addr, size_t length, int advice)
756 {
757 #if defined(HAVE_MADVISE)
758 	return (int)madvise(addr, length, advice);
759 #elif defined(__NR_madvise)
760 	return (int)syscall(__NR_madvise, addr, length, advice);
761 #elif defined(HAVE_POSIX_MADVISE)
762 	int posix_advice;
763 
764 	switch (advice) {
765 #if defined(POSIX_MADV_NORMAL) &&	\
766     defined(MADV_NORMAL)
767 	case MADV_NORMAL:
768 		posix_advice = POSIX_MADV_NORMAL;
769 		break;
770 #endif
771 #if defined(POSIX_MADV_SEQUENTIAL) &&	\
772     defined(MADV_SEQUENTIAL)
773 	case MADV_SEQUENTIAL:
774 		posix_advice = POSIX_MADV_SEQUENTIAL;
775 		break;
776 #endif
777 #if defined(POSIX_MADV_RANDOM) &&	\
778     defined(MADV_RANDOM)
779 	case MADV_RANDOM:
780 		posix_advice = POSIX_MADV_RANDOM;
781 		break;
782 #endif
783 #if defined(POSIX_MADV_WILLNEED) &&	\
784     defined(MADV_WILLNEED)
785 	case MADV_WILLNEED:
786 		posix_advice = POSIX_MADV_WILLNEED;
787 		break;
788 #endif
789 #if defined(POSIX_MADV_DONTNEED) &&	\
790     defined(MADV_DONTNEED)
791 	case MADV_DONTNEED:
792 		posix_advice = POSIX_MADV_DONTNEED;
793 		break;
794 #endif
795 	default:
796 		posix_advice = POSIX_MADV_NORMAL;
797 		break;
798 	}
799 	return (int)posix_madvise(addr, length, posix_advice);
800 #else
801 	return (int)shim_enosys(0, addr, length, advice);
802 #endif
803 }
804 
805 /*
806  *  shim_mincore()
807  *	wrapper for mincore(2) -  determine whether pages are resident in memory
808  */
shim_mincore(void * addr,size_t length,unsigned char * vec)809 int shim_mincore(void *addr, size_t length, unsigned char *vec)
810 {
811 #if defined(HAVE_MINCORE) &&	\
812     NEED_GLIBC(2,2,0)
813 #if defined(__FreeBSD__) || defined(__OpenBSD__) || \
814     defined(__NetBSD__) || defined(__sun__)
815 	return mincore(addr, length, (char *)vec);
816 #else
817 	return mincore(addr, length, vec);
818 #endif
819 #elif defined(__NR_mincore)
820 	return (int)syscall(__NR_mincore, addr, length, vec);
821 #else
822 	return (int)shim_enosys(0, addr, length, vec);
823 #endif
824 }
825 
shim_statx(int dfd,const char * filename,unsigned int flags,unsigned int mask,struct shim_statx * buffer)826 ssize_t shim_statx(
827 	int dfd,
828 	const char *filename,
829 	unsigned int flags,
830 	unsigned int mask,
831 	struct shim_statx *buffer)
832 {
833 #if defined(__NR_statx)
834 	return (ssize_t)syscall(__NR_statx, dfd, filename, flags, mask, buffer);
835 #else
836 	return (ssize_t)shim_enosys(0, dfd, filename, flags, mask, buffer);
837 #endif
838 }
839 
840 /*
841  *  futex wake()
842  *	wake n waiters on futex
843  */
shim_futex_wake(const void * futex,const int n)844 int shim_futex_wake(const void *futex, const int n)
845 {
846 #if defined(__NR_futex) &&	\
847     defined(FUTEX_WAKE)
848 	return (int)syscall(__NR_futex, futex, FUTEX_WAKE, n, NULL, NULL, 0);
849 #else
850 	return (int)shim_enosys(0, futex, 0, n, NULL, NULL, 0);
851 #endif
852 }
853 
854 /*
855  *  futex_wait()
856  *	wait on futex with a timeout
857  */
shim_futex_wait(const void * futex,const int val,const struct timespec * timeout)858 int shim_futex_wait(
859 	const void *futex,
860 	const int val,
861 	const struct timespec *timeout)
862 {
863 #if defined(__NR_futex) &&	\
864     defined(FUTEX_WAKE)
865 	return (int)syscall(__NR_futex, futex, FUTEX_WAIT, val, timeout, NULL, 0);
866 #else
867 	return (int)shim_enosys(0, futex, 0, val, timeout, NULL, 0);
868 #endif
869 }
870 
871 /*
872  *  dup3()
873  *	linux special dup3
874  */
shim_dup3(int oldfd,int newfd,int flags)875 int shim_dup3(int oldfd, int newfd, int flags)
876 {
877 #if defined(HAVE_DUP3)
878 	return dup3(oldfd, newfd, flags);
879 #elif defined(__NR_dup3)
880 	return (int)syscall(__NR_dup3, oldfd, newfd, flags);
881 #else
882 	return (int)shim_enosys(0, oldfd, newfd, flags);
883 #endif
884 }
885 
886 
shim_sync_file_range(int fd,shim_off64_t offset,shim_off64_t nbytes,unsigned int flags)887 int shim_sync_file_range(
888 	int fd,
889 	shim_off64_t offset,
890 	shim_off64_t nbytes,
891 	unsigned int flags)
892 {
893 #if defined(HAVE_SYNC_FILE_RANGE)
894 	return sync_file_range(fd, offset, nbytes, flags);
895 #elif defined(__NR_sync_file_range)
896 	return (int)syscall(__NR_sync_file_range, fd, offset, nbytes, flags);
897 #elif defined(__NR_sync_file_range2)
898 	/*
899 	 * from sync_file_range(2):
900 	 * "Some architectures (e.g., PowerPC, ARM) need  64-bit  arguments
901 	 * to be aligned in a suitable pair of registers.  On such
902 	 * architectures, the call signature of sync_file_range() shown in
903 	 * the SYNOPSIS would force a register to be wasted as padding
904 	 * between the fd and offset arguments.  (See syscall(2) for details.)
905 	 * Therefore, these architectures define a different system call that
906 	 * orders the arguments suitably"
907 	 */
908 	return (int)syscall(__NR_sync_file_range2, fd, flags, offset, nbytes);
909 #else
910 	return (int)shim_enosys(0, fd, offset, nbytes, flags);
911 #endif
912 }
913 
914 /*
915  *  shim_ioprio_set()
916  *	ioprio_set system call
917  */
shim_ioprio_set(int which,int who,int ioprio)918 int shim_ioprio_set(int which, int who, int ioprio)
919 {
920 #if defined(__NR_ioprio_set)
921 	return (int)syscall(__NR_ioprio_set, which, who, ioprio);
922 #else
923 	return (int)shim_enosys(0, which, who, ioprio);
924 #endif
925 }
926 
927 /*
928  *  shim_ioprio_get()
929  *	ioprio_get system call
930  */
shim_ioprio_get(int which,int who)931 int shim_ioprio_get(int which, int who)
932 {
933 #if defined(__NR_ioprio_get)
934 	return (int)syscall(__NR_ioprio_get, which, who);
935 #else
936 	return (int)shim_enosys(0, which, who);
937 #endif
938 }
939 
940 /*
941  *   shim_brk()
942  *	brk system call shim
943  */
944 #if defined(__APPLE__)
945 STRESS_PRAGMA_PUSH
946 STRESS_PRAGMA_WARN_OFF
947 #endif
shim_brk(void * addr)948 int shim_brk(void *addr)
949 {
950 #if defined(__APPLE__)
951 	return (int)brk(addr);
952 #elif defined(__NR_brk)
953 	int ret;
954 
955 	ret = syscall(__NR_brk, addr);
956 	(void)ret;
957 	return (errno == 0) ? 0 : ENOMEM;
958 #elif defined(HAVE_BRK)
959 	return brk(addr);
960 #else
961 	uintptr_t brkaddr;
962 	intptr_t inc;
963 	void *newbrk;
964 
965 	brkaddr = (uintptr_t)shim_sbrk(0);
966 	inc = brkaddr - (intptr_t)addr;
967 	newbrk = shim_sbrk(inc);
968 	if (newbrk == (void *)-1) {
969 		if (errno != ENOSYS)
970 			errno = ENOMEM;
971 		return -1;
972 	}
973 	return 0;
974 #endif
975 }
976 #if defined(__APPLE__)
977 STRESS_PRAGMA_POP
978 #endif
979 
980 /*
981  *   shim_sbrk()
982  *	sbrk system call shim
983  */
984 #if defined(__APPLE__)
985 STRESS_PRAGMA_PUSH
986 STRESS_PRAGMA_WARN_OFF
987 #endif
shim_sbrk(intptr_t increment)988 void *shim_sbrk(intptr_t increment)
989 {
990 #if defined(HAVE_SBRK)
991 	return sbrk(increment);
992 #elif defined(__NR_sbrk)
993 	return (void *)syscall(__NR_sbrk, increment);
994 #else
995 	return (void *)(intptr_t)shim_enosys(0, increment);
996 #endif
997 }
998 #if defined(__APPLE__)
999 STRESS_PRAGMA_POP
1000 #endif
1001 
1002 /*
1003  *   shim_strlcpy()
1004  *	wrapper / implementation of BSD strlcpy
1005  */
shim_strlcpy(char * dst,const char * src,size_t len)1006 size_t shim_strlcpy(char *dst, const char *src, size_t len)
1007 {
1008 #if defined(HAVE_BSD_STRLCPY) &&	\
1009     !defined(BUILD_STATIC)
1010 	return strlcpy(dst, src, len);
1011 #else
1012 	register char *d = dst;
1013 	register const char *s = src;
1014 	register size_t n = len;
1015 
1016 	if (n) {
1017 		while (--n) {
1018 			register char c = *s++;
1019 
1020 			*d++ = c;
1021 			if (c == '\0')
1022 				break;
1023 		}
1024 	}
1025 
1026 	if (!n) {
1027 		if (len)
1028 			*d = '\0';
1029 		while (*s)
1030 			s++;
1031 	}
1032 
1033 	return (s - src - 1);
1034 #endif
1035 }
1036 
1037 /*
1038  *   shim_strlcat()
1039  *	wrapper / implementation of BSD strlcat
1040  */
shim_strlcat(char * dst,const char * src,size_t len)1041 size_t shim_strlcat(char *dst, const char *src, size_t len)
1042 {
1043 #if defined(HAVE_BSD_STRLCAT) &&	\
1044     !defined(BUILD_STATIC)
1045 	return strlcat(dst, src, len);
1046 #else
1047 	register char *d = dst;
1048 	register const char *s = src;
1049 	register size_t n = len, tmplen;
1050 
1051 	while (n-- && *d != '\0') {
1052 		d++;
1053 	}
1054 
1055 	tmplen = d - dst;
1056 	n = len - tmplen;
1057 
1058 	if (!n) {
1059 		return strlen(s) + tmplen;
1060 	}
1061 
1062 	while (*s != '\0') {
1063 		if (n != 1) {
1064 			*d = *s;
1065 			d++;
1066 			n--;
1067 		}
1068 		s++;
1069 	}
1070 	*d = '\0';
1071 
1072 	return (s - src) + tmplen;
1073 #endif
1074 }
1075 
1076 /*
1077  *  shim_fsync
1078  *	wrapper for fsync
1079  */
shim_fsync(int fd)1080 int shim_fsync(int fd)
1081 {
1082 #if defined(__APPLE__) &&	\
1083     defined(F_FULLFSYNC)
1084 	int ret;
1085 
1086 	/*
1087 	 *  For APPLE Mac OS X try to use the full fsync fcntl
1088 	 *  first and then fall back to a potential no-op'd fsync
1089 	 *  implementation.
1090 	 */
1091 	ret = fcntl(fd, F_FULLFSYNC, NULL);
1092 	if (ret == 0)
1093 		return 0;
1094 #endif
1095 	return fsync(fd);
1096 }
1097 
1098 /*
1099  *  shim_fdatasync
1100  *	wrapper for fdatasync
1101  */
shim_fdatasync(int fd)1102 int shim_fdatasync(int fd)
1103 {
1104 #if defined(HAVE_FDATASYNC)
1105 	/*
1106 	 *  For some reason, fdatasync prototype may be missing
1107 	 *  in some __APPLE__ systems.
1108 	 */
1109 #if defined(__APPLE__)
1110 	extern int fdatasync(int fd);
1111 #endif
1112 	return fdatasync(fd);
1113 #elif defined(__NR_fdatasync)
1114 	return (int)syscall(__NR_fdatasync, fd);
1115 #else
1116 	return (int)shim_enosys(0, fd);
1117 #endif
1118 }
1119 
1120 /*
1121  *   shim_pkey_alloc()
1122  *	wrapper for pkey_alloc()
1123  */
shim_pkey_alloc(unsigned long flags,unsigned long access_rights)1124 int shim_pkey_alloc(unsigned long flags, unsigned long access_rights)
1125 {
1126 #if defined(HAVE_PKEY_ALLOC)
1127 	return pkey_alloc(flags, access_rights);
1128 #elif defined(__NR_pkey_alloc)
1129 	return (int)syscall(__NR_pkey_alloc, flags, access_rights);
1130 #else
1131 	return (int)shim_enosys(0, flags, access_rights);
1132 #endif
1133 }
1134 
1135 /*
1136  *   shim_pkey_free()
1137  *	wrapper for pkey_free()
1138  */
shim_pkey_free(int pkey)1139 int shim_pkey_free(int pkey)
1140 {
1141 #if defined(HAVE_PKEY_FREE)
1142 	return pkey_free(pkey);
1143 #elif defined(__NR_pkey_free)
1144 	return (int)syscall(__NR_pkey_free, pkey);
1145 #else
1146 	return (int)shim_enosys(0, pkey);
1147 #endif
1148 }
1149 
1150 /*
1151  *   shim_pkey_mprotect()
1152  *	wrapper for pkey_mprotect()
1153  */
shim_pkey_mprotect(void * addr,size_t len,int prot,int pkey)1154 int shim_pkey_mprotect(void *addr, size_t len, int prot, int pkey)
1155 {
1156 #if defined(HAVE_PKEY_MPROTECT)
1157 	return pkey_mprotect(addr, len, prot, pkey);
1158 #elif defined(__NR_pkey_mprotect)
1159 	return (int)syscall(__NR_pkey_mprotect, addr, len, prot, pkey);
1160 #else
1161 	return (int)shim_enosys(0, addr, len, prot, pkey);
1162 #endif
1163 }
1164 
1165 /*
1166  *   shim_pkey_get()
1167  *	wrapper for pkey_get()
1168  */
shim_pkey_get(int pkey)1169 int shim_pkey_get(int pkey)
1170 {
1171 #if defined(HAVE_PKEY_GET)
1172 	return pkey_get(pkey);
1173 #elif defined(__NR_pkey_get)
1174 	return (int)syscall(__NR_pkey_get, pkey);
1175 #else
1176 	return (int)shim_enosys(0, pkey);
1177 #endif
1178 }
1179 
1180 /*
1181  *   shim_pkey_set()
1182  *	wrapper for pkey_set()
1183  */
shim_pkey_set(int pkey,unsigned int rights)1184 int shim_pkey_set(int pkey, unsigned int rights)
1185 {
1186 #if defined(HAVE_PKEY_SET)
1187 	return pkey_set(pkey, rights);
1188 #elif defined(__NR_pkey_set)
1189 	return (int)syscall(__NR_pkey_set, pkey, rights);
1190 #else
1191 	return (int)shim_enosys(0, pkey, rights);
1192 #endif
1193 }
1194 
1195 /*
1196  *   shim_execveat()
1197  *	wrapper for execveat()
1198  */
shim_execveat(int dir_fd,const char * pathname,char * const argv[],char * const envp[],int flags)1199 int shim_execveat(
1200 	int dir_fd,
1201 	const char *pathname,
1202 	char *const argv[],
1203 	char *const envp[],
1204 	int flags)
1205 {
1206 #if defined(__NR_execveat)
1207 	return (int)syscall(__NR_execveat, dir_fd, pathname, argv, envp, flags);
1208 #else
1209 	return (int)shim_enosys(0, dir_fd, pathname, argv, envp, flags);
1210 #endif
1211 }
1212 
1213 /*
1214  *   shim_waitpid()
1215  *	wrapper for waitpid with EINTR retry
1216  */
shim_waitpid(pid_t pid,int * wstatus,int options)1217 pid_t shim_waitpid(pid_t pid, int *wstatus, int options)
1218 {
1219 	pid_t ret;
1220 	int count = 0;
1221 
1222 	for (;;) {
1223 		errno = 0;
1224 		ret = waitpid(pid, wstatus, options);
1225 		if ((ret >= 0) || (errno != EINTR))
1226 			break;
1227 
1228 		count++;
1229 		/*
1230 		 *  Retry if EINTR unless we've have 2 mins
1231 		 *  consecutive EINTRs then give up.
1232 		 */
1233 		if (!keep_stressing_flag()) {
1234 			(void)kill(pid, SIGALRM);
1235 			if (count > 120)
1236 				(void)kill(pid, SIGKILL);
1237 		}
1238 		if (count > 10)
1239 			(void)sleep(1);
1240 	}
1241 	return ret;
1242 }
1243 
1244 /*
1245  *   shim_wait()
1246  *	shim wrapper for wait, try waitpid if available
1247  */
shim_wait(int * wstatus)1248 pid_t shim_wait(int *wstatus)
1249 {
1250 #if defined(__NR_waitpid)
1251 	return (pid_t)syscall(__NR_waitpid, -1, wstatus, 0);
1252 #else
1253 	return wait(wstatus);
1254 #endif
1255 }
1256 
1257 /*
1258  *   shim_wait3(()
1259  *	wrapper for wait3()
1260  *
1261  */
shim_wait3(int * wstatus,int options,struct rusage * rusage)1262 pid_t shim_wait3(int *wstatus, int options, struct rusage *rusage)
1263 {
1264 #if defined(__NR_wait3)
1265 	return (pid_t)syscall(__NR_wait3, wstatus, options, rusage);
1266 #elif defined(HAVE_WAIT3)
1267 	return wait3(wstatus, options, rusage);
1268 #else
1269 	return (pid_t)shim_enosys(0, wstatus, options, rusage);
1270 #endif
1271 }
1272 
1273 /*
1274  *   shim_wait4(()
1275  *	wrapper for wait4()
1276  *
1277  */
shim_wait4(pid_t pid,int * wstatus,int options,struct rusage * rusage)1278 pid_t shim_wait4(pid_t pid, int *wstatus, int options, struct rusage *rusage)
1279 {
1280 #if defined(__NR_wait4)
1281 	return (pid_t)syscall(__NR_wait4, pid, wstatus, options, rusage);
1282 #elif defined(HAVE_WAIT4)
1283 	return wait4(pid, wstatus, options, rusage);
1284 #else
1285 	return (pid_t)shim_enosys(0, pid, wstatus, options, rusage);
1286 #endif
1287 }
1288 
1289 /*
1290  *   shim_exit_group()
1291  *	wrapper for exit_group(), fall back to _exit() if it does
1292  *	not exist
1293  */
shim_exit_group(int status)1294 void shim_exit_group(int status)
1295 {
1296 #if defined(__NR_exit_group)
1297 	(void)syscall(__NR_exit_group, status);
1298 #else
1299 	_exit(status);
1300 #endif
1301 }
1302 
1303 /*
1304  *   shim_pidfd_send_signal()
1305  *	wrapper for pidfd_send_signal added to Linux 5.1
1306  */
shim_pidfd_send_signal(int pidfd,int sig,siginfo_t * info,unsigned int flags)1307 int shim_pidfd_send_signal(
1308 	int pidfd,
1309 	int sig,
1310 	siginfo_t *info,
1311 	unsigned int flags)
1312 {
1313 #if defined(__NR_pidfd_send_signal)
1314 	return (int)syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
1315 #else
1316 	return (int)shim_enosys(0, pidfd, sig, info, flags);
1317 #endif
1318 }
1319 
1320 /*
1321  *   shim_pidfd_open()
1322  *	wrapper for pidfd_open
1323  */
shim_pidfd_open(pid_t pid,unsigned int flags)1324 int shim_pidfd_open(pid_t pid, unsigned int flags)
1325 {
1326 #if defined(HAVE_PIDFD_OPEN)
1327 	return pidfd_open(pid, flags);
1328 #elif defined(__NR_pidfd_open)
1329 	return (int)syscall(__NR_pidfd_open, pid, flags);
1330 #else
1331 	return (int)shim_enosys(0, pid, flags);
1332 #endif
1333 }
1334 
1335 /*
1336  *   shim_pidfd_getfd()
1337  *	wrapper for pidfd_getfd
1338  */
shim_pidfd_getfd(int pidfd,int targetfd,unsigned int flags)1339 int shim_pidfd_getfd(int pidfd, int targetfd, unsigned int flags)
1340 {
1341 #if defined(HAVE_PIDFD_GETFD)
1342 	return pidfd_getfd(pidfd, targetfd, flags);
1343 #elif defined(__NR_pidfd_getfd)
1344 	return (int)syscall(__NR_pidfd_getfd, pidfd, targetfd, flags);
1345 #else
1346 	return (int)shim_enosys(0, pidfd, targetfd, flags);
1347 #endif
1348 }
1349 
1350 /*
1351  * If we have the fancy new Linux 5.2 mount system
1352  * calls then provide shim wrappers for these
1353  */
shim_fsopen(const char * fsname,unsigned int flags)1354 int shim_fsopen(const char *fsname, unsigned int flags)
1355 {
1356 #if defined(__NR_fsopen)
1357 	return (int)syscall(__NR_fsopen, fsname, flags);
1358 #else
1359 	return (int)shim_enosys(0, fsname, flags);
1360 #endif
1361 }
1362 
shim_fsmount(int fd,unsigned int flags,unsigned int ms_flags)1363 int shim_fsmount(int fd, unsigned int flags, unsigned int ms_flags)
1364 {
1365 #if defined(__NR_fsmount)
1366 	return (int)syscall(__NR_fsmount, fd, flags, ms_flags);
1367 #else
1368 	return (int)shim_enosys(0, fd, flags, ms_flags);
1369 #endif
1370 }
1371 
shim_fsconfig(int fd,unsigned int cmd,const char * key,const void * value,int aux)1372 int shim_fsconfig(
1373 	int fd,
1374 	unsigned int cmd,
1375 	const char *key,
1376 	const void *value,
1377 	int aux)
1378 {
1379 #if defined(__NR_fsconfig)
1380 	return (int)syscall(__NR_fsconfig, fd, cmd, key, value, aux);
1381 #else
1382 	return (int)shim_enosys(0, fd, cmd, key, value, aux);
1383 #endif
1384 }
1385 
shim_move_mount(int from_dfd,const char * from_pathname,int to_dfd,const char * to_pathname,unsigned int flags)1386 int shim_move_mount(
1387 	int from_dfd,
1388 	const char *from_pathname,
1389 	int to_dfd,
1390 	const char *to_pathname,
1391 	unsigned int flags)
1392 {
1393 #if defined(__NR_move_mount)
1394 	return (int)syscall(__NR_move_mount, from_dfd, from_pathname,
1395 		to_dfd, to_pathname, flags);
1396 #else
1397 	return (int)shim_enosys(0, from_dfd, from_pathname,
1398 		to_dfd, to_pathname, flags);
1399 #endif
1400 }
1401 
sys_clone3(struct shim_clone_args * cl_args,size_t size)1402 int sys_clone3(struct shim_clone_args *cl_args, size_t size)
1403 {
1404 #if defined(__NR_clone3)
1405 	return (int)syscall(__NR_clone3, cl_args, size);
1406 #else
1407 	return (int)shim_enosys(0, cl_args, size);
1408 #endif
1409 }
1410 
shim_ustat(dev_t dev,struct shim_ustat * ubuf)1411 int shim_ustat(dev_t dev, struct shim_ustat *ubuf)
1412 {
1413 #if defined(HAVE_USTAT) &&	\
1414      defined(HAVE_USTAT_H)
1415 	return ustat(dev, (void *)ubuf);
1416 #elif defined(__NR_ustat)
1417 	return (int)syscall(__NR_ustat, dev, ubuf);
1418 #else
1419 	return (int)shim_enosys(0, dev, ubuf);
1420 #endif
1421 }
1422 
1423 /*
1424  *   shim_getxattr
1425  *	wrapper for getxattr
1426  */
shim_getxattr(const char * path,const char * name,void * value,size_t size)1427 ssize_t shim_getxattr(
1428 	const char *path,
1429 	const char *name,
1430 	void *value,
1431 	size_t size)
1432 {
1433 #if defined(HAVE_GETXATTR)
1434 #if defined(__APPLE__)
1435 	return getxattr(path, name, value, size, 0, 0);
1436 #else
1437 	return getxattr(path, name, value, size);
1438 #endif
1439 #elif defined(__NR_getxattr)
1440 	return (ssize_t)syscall(__NR_getxattr, path, name, value, size);
1441 #else
1442 	return (ssize_t)shim_enosys(0, path, name, value, size);
1443 #endif
1444 }
1445 
1446 /*
1447  *  shim_listxattr
1448  *	wrapper for listxattr
1449  */
shim_listxattr(const char * path,char * list,size_t size)1450 ssize_t shim_listxattr(const char *path, char *list, size_t size)
1451 {
1452 #if defined(HAVE_LISTXATTR)
1453 #if defined(__APPLE__)
1454 	return listxattr(path, list, size, 0);
1455 #else
1456 	return listxattr(path, list, size);
1457 #endif
1458 #elif defined(__NR_listxattr)
1459 	return (ssize_t)syscall(__NR_listxattr, path, list, size);
1460 #else
1461 	return (ssize_t)shim_enosys(0, path, list, size);
1462 #endif
1463 }
1464 
1465 /*
1466  *  shim_flistxattr
1467  *	wrapper for flistxattr
1468  */
shim_flistxattr(int fd,char * list,size_t size)1469 ssize_t shim_flistxattr(int fd, char *list, size_t size)
1470 {
1471 #if defined(HAVE_FLISTXATTR)
1472 #if defined(__APPLE__)
1473 	return flistxattr(fd, list, size, 0);
1474 #else
1475 	return flistxattr(fd, list, size);
1476 #endif
1477 #elif defined(__NR_flistxattr)
1478 	return (ssize_t)syscall(__NR_flistxattr, fd, list, size);
1479 #else
1480 	return (ssize_t)shim_enosys(0, fd, list, size);
1481 #endif
1482 }
1483 
1484 /*
1485  *  shim_setxattr
1486  *	wrapper for setxattr
1487  */
shim_setxattr(const char * path,const char * name,const void * value,size_t size,int flags)1488 int shim_setxattr(const char *path, const char *name, const void *value, size_t size, int flags)
1489 {
1490 #if defined(HAVE_SETXATTR)
1491 #if defined(__APPLE__)
1492 	return setxattr(path, name, value, size, 0, flags);
1493 #else
1494 	return setxattr(path, name, value, size, flags);
1495 #endif
1496 #elif defined(__NR_setxattr)
1497 	return (int)syscall(__NR_setxattr, path, name, value, size, flags);
1498 #else
1499 	return (int)shim_enosys(0, path, name, value, size, flags);
1500 #endif
1501 }
1502 
1503 /*
1504  *  shim_fsetxattr
1505  *	wrapper for fsetxattr
1506  */
shim_fsetxattr(int fd,const char * name,const void * value,size_t size,int flags)1507 int shim_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags)
1508 {
1509 #if defined(HAVE_FSETXATTR)
1510 #if defined(__APPLE__)
1511 	return fsetxattr(fd, name, value, size, 0, flags);
1512 #else
1513 	return fsetxattr(fd, name, value, size, flags);
1514 #endif
1515 #elif defined(__NR_fsetxattr)
1516 	return (int)syscall(__NR_fsetxattr, fd, name, value, size, flags);
1517 #else
1518 	return (int)shim_enosys(0, fd, name, value, size, flags);
1519 #endif
1520 }
1521 
1522 /*
1523  *  shim_lsetxattr
1524  *	wrapper for lsetxattr
1525  */
shim_lsetxattr(const char * path,const char * name,const void * value,size_t size,int flags)1526 int shim_lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags)
1527 {
1528 #if defined(HAVE_LSETXATTR)
1529 	return lsetxattr(path, name, value, size, flags);
1530 #elif defined(__NR_lsetxattr)
1531 	return (int)syscall(__NR_lsetxattr, path, name, value, size, flags);
1532 #else
1533 	return (int)shim_enosys(0, path, name, value, size, flags);
1534 #endif
1535 }
1536 
1537 /*
1538  *  shim_lgetxattr
1539  *	wrapper for lgetxattr
1540  */
shim_lgetxattr(const char * path,const char * name,void * value,size_t size)1541 ssize_t shim_lgetxattr(const char *path, const char *name, void *value, size_t size)
1542 {
1543 #if defined(HAVE_LGETXATTR)
1544 	return lgetxattr(path, name, value, size);
1545 #elif defined(__NR_lgetxattr)
1546 	return (ssize_t)syscall(__NR_lgetxattr, path, name, value, size);
1547 #else
1548 	return (ssize_t)shim_enosys(0, path, name, value, size);
1549 #endif
1550 }
1551 
1552 /*
1553  *  shim_fgetxattr
1554  *	wrapper for fgetxattr
1555  */
shim_fgetxattr(int fd,const char * name,void * value,size_t size)1556 ssize_t shim_fgetxattr(int fd, const char *name, void *value, size_t size)
1557 {
1558 #if defined(HAVE_FGETXATTR)
1559 #if defined(__APPLE__)
1560 	return fgetxattr(fd, name, value, size, 0, 0);
1561 #else
1562 	return fgetxattr(fd, name, value, size);
1563 #endif
1564 #elif defined(__NR_fgetxattr)
1565 	return (ssize_t)syscall(__NR_fgetxattr, fd, name, value, size);
1566 #else
1567 	return (ssize_t)shim_enosys(0, fd, name, value, size);
1568 #endif
1569 }
1570 
1571 /*
1572  *  shim_removexattr
1573  *	wrapper for removexattr
1574  */
shim_removexattr(const char * path,const char * name)1575 int shim_removexattr(const char *path, const char *name)
1576 {
1577 #if defined(HAVE_REMOVEXATTR)
1578 #if defined(__APPLE__)
1579 	return removexattr(path, name, 0);
1580 #else
1581 	return removexattr(path, name);
1582 #endif
1583 #elif defined(__NR_removexattr)
1584 	return (int)syscall(__NR_removexattr, path, name);
1585 #else
1586 	return (int)shim_enosys(0, path, name);
1587 #endif
1588 }
1589 
1590 /*
1591  *  shim_lremovexattr
1592  *	wrapper for lremovexattr
1593  */
shim_lremovexattr(const char * path,const char * name)1594 int shim_lremovexattr(const char *path, const char *name)
1595 {
1596 #if defined(HAVE_LREMOVEXATTR)
1597 	return lremovexattr(path, name);
1598 #elif defined(__NR_lremovexattr)
1599 	return (int)syscall(__NR_lremovexattr, path, name);
1600 #else
1601 	return (int)shim_enosys(0, path, name);
1602 #endif
1603 }
1604 
1605 /*
1606  *  shim_fremovexattr
1607  *	wrapper for fremovexattr
1608  */
shim_fremovexattr(int fd,const char * name)1609 int shim_fremovexattr(int fd, const char *name)
1610 {
1611 #if defined(HAVE_FREMOVEXATTR)
1612 #if defined(__APPLE__)
1613 	return fremovexattr(fd, name, 0);
1614 #else
1615 	return fremovexattr(fd, name);
1616 #endif
1617 #elif defined(__NR_fremovexattr)
1618 	return (int)syscall(__NR_fremovexattr, fd, name);
1619 #else
1620 	return (int)shim_enosys(0, fd, name);
1621 #endif
1622 }
1623 
1624 /*
1625  *  shim_llistxattr
1626  *	wrapper for fllistxattr
1627  */
shim_llistxattr(const char * path,char * list,size_t size)1628 ssize_t shim_llistxattr(const char *path, char *list, size_t size)
1629 {
1630 #if defined(HAVE_LLISTXATTR)
1631 	return llistxattr(path, list, size);
1632 #elif defined(__NR_llistxattr)
1633 	return (ssize_t)syscall(__NR_llistxattr, path, list, size);
1634 #else
1635 	return (ssize_t)shim_enosys(0, path, list, size);
1636 #endif
1637 }
1638 
1639 /*
1640  *  shim_reboot
1641  *	wrapper for linux reboot system call
1642  */
shim_reboot(int magic,int magic2,int cmd,void * arg)1643 int shim_reboot(int magic, int magic2, int cmd, void *arg)
1644 {
1645 #if defined(__linux__) &&	\
1646     defined(__NR_reboot)
1647 	return (int)syscall(__NR_reboot, magic, magic2, cmd, arg);
1648 #else
1649 	return (int)shim_enosys(0, magic, magic2, cmd, arg);
1650 #endif
1651 }
1652 
1653 /*
1654  *   shim_process_madvise
1655  *	wrapper for the new linux 5.10 process_madvise system call
1656  *	ref: commit 28a305ae24da ("mm/madvise: introduce process_madvise()
1657  *	syscall: an external memory hinting API"
1658  */
shim_process_madvise(int pidfd,const struct iovec * iovec,unsigned long vlen,int advice,unsigned int flags)1659 ssize_t shim_process_madvise(
1660 	int pidfd,
1661 	const struct iovec *iovec,
1662 	unsigned long vlen,
1663 	int advice,
1664 	unsigned int flags)
1665 {
1666 #if defined(__NR_process_madvise)
1667 	return (ssize_t)syscall(__NR_process_madvise, pidfd,
1668 		iovec, vlen, advice, flags);
1669 #else
1670 	return (ssize_t)shim_enosys(0, pidfd,
1671 		iovec, vlen, advice, flags);
1672 #endif
1673 }
1674 
1675 /*
1676  *   shim_clock_adjtime
1677  *	wrapper for linux clock_adjtime system call
1678  */
shim_clock_adjtime(clockid_t clk_id,struct shim_timex * tx)1679 int shim_clock_adjtime(clockid_t clk_id, struct shim_timex *tx)
1680 {
1681 #if defined(HAVE_SYS_TIMEX_H) &&	\
1682     defined(CLOCK_THREAD_CPUTIME_ID) &&	\
1683     defined(__NR_clock_adjtime)
1684 	return (int)syscall(__NR_clock_adjtime, clk_id, tx);
1685 #else
1686 	return (int)shim_enosys(0, clk_id, tx);
1687 #endif
1688 }
1689 
1690 /*
1691  *   shim_clock_getres
1692  *	wrapper for linux clock_getres system call,
1693  *	prefer to use the system call to avoid and
1694  *	glibc avoidance of the system call
1695  */
shim_clock_getres(clockid_t clk_id,struct timespec * res)1696 int shim_clock_getres(clockid_t clk_id, struct timespec *res)
1697 {
1698 #if defined(CLOCK_THREAD_CPUTIME_ID) && \
1699     defined(HAVE_CLOCK_GETRES)
1700 #if defined(__NR_clock_getres)
1701 	return (int)syscall(__NR_clock_getres, clk_id, res);
1702 #else
1703 	return clock_getres(clk_id, res);
1704 #endif
1705 #else
1706 	return (int)shim_enosys(0, clk_id, res);
1707 #endif
1708 }
1709 
1710 /*
1711  *   shim_clock_gettime
1712  *	wrapper for linux clock_gettime system call,
1713  *	prefer to use the system call to avoid and
1714  *	glibc avoidance of the system call
1715  */
shim_clock_gettime(clockid_t clk_id,struct timespec * tp)1716 int shim_clock_gettime(clockid_t clk_id, struct timespec *tp)
1717 {
1718 #if defined(CLOCK_THREAD_CPUTIME_ID) && \
1719     defined(HAVE_CLOCK_GETTIME)
1720 #if defined(__NR_clock_gettime)
1721 	return (int)syscall(__NR_clock_gettime, clk_id, tp);
1722 #else
1723 	return clock_gettime(clk_id, tp);
1724 #endif
1725 #else
1726 	return (int)shim_enosys(0, clk_id, tp);
1727 #endif
1728 }
1729 
1730 /*
1731  *   shim_clock_settime
1732  *	wrapper for linux clock_settime system call,
1733  *	prefer to use the system call to avoid and
1734  *	glibc avoidance of the system call
1735  */
shim_clock_settime(clockid_t clk_id,struct timespec * tp)1736 int shim_clock_settime(clockid_t clk_id, struct timespec *tp)
1737 {
1738 #if defined(CLOCK_THREAD_CPUTIME_ID) && \
1739     defined(HAVE_CLOCK_SETTIME)
1740 #if defined(__NR_clock_settime)
1741 	return (int)syscall(__NR_clock_settime, clk_id, tp);
1742 #else
1743 	return clock_settime(clk_id, tp);
1744 #endif
1745 #else
1746 	return (int)shim_enosys(0, clk_id, tp);
1747 #endif
1748 }
1749 
1750 /*
1751  *  shim_nice
1752  *	wrapper for nice.  Some C libraries may use setpriority
1753  *	and hence the nice system call is not being used. Directly
1754  *	call the nice system call if it's available, else use the
1755  *	libc version.
1756  *
1757  *	Some operating systems like Hiaku don't even support nice,
1758  *	so handle these cases too.
1759  */
shim_nice(int inc)1760 int shim_nice(int inc)
1761 {
1762 #if defined(__NR_nice)
1763 	return (int)syscall(__NR_nice, inc);
1764 #elif defined(HAVE_NICE)
1765 	return nice(inc);
1766 #else
1767 	(void)inc;
1768 
1769 	errno = -ENOSYS;
1770 	return -1;
1771 #endif
1772 }
1773 
1774 /*
1775  *  shim_time
1776  *	wrapper for time system call to
1777  *	avoid libc calling gettimeofday via
1778  *	the VDSO and force the time system call
1779  */
shim_time(time_t * tloc)1780 time_t shim_time(time_t *tloc)
1781 {
1782 #if defined(__NR_time)
1783 	return (time_t)syscall(__NR_time, tloc);
1784 #else
1785 	return (time_t)shim_enosys(0, tloc);
1786 #endif
1787 }
1788 
1789 /*
1790  *  shim_gettimeofday
1791  *	wrapper for gettimeofday system call to
1792  *	avoid libc calling gettimeofday via
1793  *	the VDSO and force the time system call
1794  */
shim_gettimeofday(struct timeval * tv,struct timezone * tz)1795 int shim_gettimeofday(struct timeval *tv, struct timezone *tz)
1796 {
1797 #if defined(__NR_gettimeofday)
1798 	return (int)syscall(__NR_gettimeofday, tv, tz);
1799 #else
1800 	return (int)shim_enosys(0, tv, tz);
1801 #endif
1802 }
1803 
1804 /*
1805  *  shim_close_range()
1806  *	wrapper for close_range - close a range of
1807  *	file descriptors
1808  */
shim_close_range(unsigned int fd,unsigned int max_fd,unsigned int flags)1809 int shim_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags)
1810 {
1811 #if defined(__NR_close_range)
1812 	return (int)syscall(__NR_close_range, fd, max_fd, flags);
1813 #else
1814 	return (int)shim_enosys(0, fd, max_fd, flags);
1815 #endif
1816 }
1817 
1818 /*
1819  *  shim_lookup_dcookie()
1820  *	wrapper for linux lookup_dcookie
1821  */
shim_lookup_dcookie(uint64_t cookie,char * buffer,size_t len)1822 int shim_lookup_dcookie(uint64_t cookie, char *buffer, size_t len)
1823 {
1824 #if defined(__NR_lookup_dcookie)
1825 	return (int)syscall(__NR_lookup_dcookie, cookie, buffer, len);
1826 #else
1827 	return (int)shim_enosys(0, cookie, buffer, len);
1828 #endif
1829 }
1830 
1831 /*
1832  *  shim_readlink()
1833  *	wrapper for readlink because some libc wrappers call
1834  *	readlinkat
1835  */
shim_readlink(const char * pathname,char * buf,size_t bufsiz)1836 ssize_t shim_readlink(const char *pathname, char *buf, size_t bufsiz)
1837 {
1838 #if defined(__NR_readlink)
1839 	return (ssize_t)syscall(__NR_readlink, pathname, buf, bufsiz);
1840 #else
1841 	return readlink(pathname, buf, bufsiz);
1842 #endif
1843 }
1844 
1845 /*
1846  *  shim_sgetmask
1847  *	wrapper for obsolute linux system call sgetmask()
1848  */
shim_sgetmask(void)1849 long shim_sgetmask(void)
1850 {
1851 #if defined(__NR_sgetmask)
1852 	return (long)syscall(__NR_sgetmask);
1853 #else
1854 	return (long)shim_enosys(0);
1855 #endif
1856 }
1857 
1858 /*
1859  *  shim_ssetmask
1860  *	wrapper for obsolute linux system call ssetmask()
1861  */
shim_ssetmask(long newmask)1862 long shim_ssetmask(long newmask)
1863 {
1864 #if defined(__NR_ssetmask)
1865 	return (long)syscall(__NR_ssetmask, newmask);
1866 #else
1867 	return (long)shim_enosys(0, newmask);
1868 #endif
1869 }
1870 
1871 /*
1872  *  shim_stime()
1873  *	wrapper for obsolete SVr4 stime system call
1874  */
shim_stime(const time_t * t)1875 int shim_stime(const time_t *t)
1876 {
1877 #if defined(HAVE_STIME)
1878 #if defined(__minix__)
1879 	/*
1880 	 *  Minix does not provide the prototype for stime
1881 	 *  and does not use a const time_t * argument
1882 	 */
1883 	int stime(time_t *t);
1884 	time_t *ut = (time_t *)shim_unconstify_ptr(t);
1885 
1886 	return stime(ut);
1887 #else
1888 	return stime(t);
1889 #endif
1890 #elif defined(__NR_stime)
1891 	return (int)syscall(__NR_stime, t);
1892 #else
1893 	return (int)shim_enosys(0, t);
1894 #endif
1895 }
1896 
1897 /*
1898  *  shim_vhangup()
1899  *	wrapper for linux vhangup system call
1900  */
shim_vhangup(void)1901 int shim_vhangup(void)
1902 {
1903 #if defined(HAVE_VHANGUP)
1904 	return vhangup();
1905 #elif defined(__NR_vhangup)
1906 	return (int)syscall(__NR_vhangup);
1907 #else
1908 	return (int)shim_enosys(0);
1909 #endif
1910 }
1911 
1912 /*
1913  *  shim_arch_prctl()
1914  *	wrapper for arch specific prctl system call
1915  */
shim_arch_prctl(int code,unsigned long addr)1916 int shim_arch_prctl(int code, unsigned long addr)
1917 {
1918 #if defined(HAVE_ARCH_PRCTL) &&		\
1919     defined(__linux__)
1920         extern int arch_prctl();
1921 
1922         return arch_prctl(code, addr);
1923 #elif defined(__NR_arch_prctl) && 	\
1924       defined(__linux__)
1925         return (int)syscall(__NR_arch_prctl, code, addr);
1926 #else
1927         return (int)shim_enosys(0, code, addr);
1928 #endif
1929 }
1930 
1931 /*
1932  *  shim_tgkill()
1933  *	wrapper for linux thread kill tgkill system call
1934  */
shim_tgkill(int tgid,int tid,int sig)1935 int shim_tgkill(int tgid, int tid, int sig)
1936 {
1937 #if defined(HAVE_TGKILL_LIBC)
1938 	return tgkill(tgid, tid, sig);
1939 #elif defined(__NR_tgkill)
1940 	return (int)syscall(__NR_tgkill, tgid, tid, sig);
1941 #else
1942 	return (int)shim_enosys(0, tgid, tid, sig);
1943 #endif
1944 }
1945 
1946 /*
1947  *  shim_tkill()
1948  *	wrapper for deprecated thread kill tkill system
1949  *	call. No libc wrapper, so just try system call,
1950  *      then emulate via tgkill.
1951  */
shim_tkill(int tid,int sig)1952 int shim_tkill(int tid, int sig)
1953 {
1954 #if defined(__NR_tkill)
1955 	return (int)syscall(__NR_tkill, tid, sig);
1956 #else
1957 	return shim_tgkill(0, tid, sig);
1958 #endif
1959 }
1960 
1961 /*
1962  *  shim_memfd_secret()
1963  *	wrapper for the new memfd_secret system call
1964  */
shim_memfd_secret(unsigned long flags)1965 int shim_memfd_secret(unsigned long flags)
1966 {
1967 #if defined(__NR_memfd_secret)
1968 	return (int)syscall(__NR_memfd_secret, flags);
1969 #else
1970 	return (int)shim_enosys(0, flags);
1971 #endif
1972 }
1973 
1974 /*
1975  *   shim_getrusage()
1976  *	wrapper for getrusage
1977  */
shim_getrusage(int who,struct rusage * usage)1978 int shim_getrusage(int who, struct rusage *usage)
1979 {
1980 #if defined(HAVE_GETRUSAGE)
1981 	return getrusage(who, usage);
1982 #elif defined(__NR_getrusage)
1983 	return (int)syscall(__NR_getrusage, who, usage);
1984 #else
1985 	return (int)shim_enosys(0, who, usage);
1986 #endif
1987 }
1988 
1989 /*
1990  *  shim_quotactl_fd()
1991  *  	wrapper for Linux 5.13 quotactl_fd
1992  */
shim_quotactl_fd(unsigned int fd,unsigned int cmd,int id,void * addr)1993 int shim_quotactl_fd(unsigned int fd, unsigned int cmd, int id, void *addr)
1994 {
1995 #if defined(HAVE_QUOTACTL_FD)
1996 	return quotactl_fd(fd, cmd, id, addr);
1997 #elif defined(__NR_quotactl_fd)
1998 	return (int)syscall(__NR_quotactl_fd, fd, cmd, id, addr);
1999 #else
2000 	return (int)shim_enosys(0, fd, cmd, id, addr);
2001 #endif
2002 }
2003 
2004 /*
2005  *  shim_modify_ldt()
2006  *	system call wrapper for modify_ldt()
2007  */
shim_modify_ldt(int func,void * ptr,unsigned long bytecount)2008 int shim_modify_ldt(int func, void *ptr, unsigned long bytecount)
2009 {
2010 #if defined(HAVE_MODIFY_LDT) &&	\
2011      defined(__NR_modify_ldt)
2012 	return (int)syscall(__NR_modify_ldt, func, ptr, bytecount);
2013 #else
2014 	return (int)shim_enosys(0, func, ptr, bytecount);
2015 #endif
2016 }
2017 
2018 /*
2019  *  shim_process_mrelease()
2020  *	system call wrapper for Linux 5.14 process_mrelease
2021  */
shim_process_mrelease(int pidfd,unsigned int flags)2022 int shim_process_mrelease(int pidfd, unsigned int flags)
2023 {
2024 #if defined(__NR_process_release)
2025 	return (int)syscall(__NR_process_release, pidfd, flags);
2026 #else
2027 	return (int)shim_enosys(0, pidfd, flags);
2028 #endif
2029 }
2030 
2031 /*
2032  *  shim_futex_waitv()
2033  *      system call wrapper for Linux 5.16 futex_waitv
2034  */
shim_futex_waitv(struct shim_futex_waitv * waiters,unsigned int nr_futexes,unsigned int flags,struct timespec * timeout,clockid_t clockid)2035 int shim_futex_waitv(
2036 	struct shim_futex_waitv *waiters,
2037 	unsigned int nr_futexes,
2038 	unsigned int flags,
2039 	struct timespec *timeout,
2040 	clockid_t clockid)
2041 {
2042 #if defined(__NR_futex_waitv)
2043 	return (int)syscall(__NR_futex_waitv, waiters, nr_futexes, flags, timeout, clockid);
2044 #else
2045 	return (int)shim_enosys(0, waiters, nr_futexes, flags, timeout, clockid);
2046 #endif
2047 }
2048