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