1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
4 * Copyright (c) 2017-2024 Linux Test Project
5 */
6
7 #define _GNU_SOURCE
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <sched.h>
12 #include <sys/ptrace.h>
13 #include <sys/prctl.h>
14 #include "config.h"
15 #ifdef HAVE_SYS_FANOTIFY_H
16 # include <sys/fanotify.h>
17 #endif
18 #define TST_NO_DEFAULT_MAIN
19 #include "tst_test.h"
20 #include "lapi/setns.h"
21 #include "tst_safe_macros.h"
22 #include "lapi/personality.h"
23 #include "lapi/pidfd.h"
24
safe_access(const char * file,const int lineno,const char * pathname,int mode)25 int safe_access(const char *file, const int lineno,
26 const char *pathname, int mode)
27 {
28 int rval;
29
30 rval = access(pathname, mode);
31
32 if (rval == -1) {
33 tst_brk_(file, lineno, TBROK | TERRNO,
34 "access(%s,%d) failed", pathname, mode);
35 } else if (rval) {
36 tst_brk_(file, lineno, TBROK | TERRNO,
37 "Invalid access(%s,%d) return value %d", pathname,
38 mode, rval);
39 }
40
41 return rval;
42 }
43
safe_setpgid(const char * file,const int lineno,pid_t pid,pid_t pgid)44 int safe_setpgid(const char *file, const int lineno, pid_t pid, pid_t pgid)
45 {
46 int rval;
47
48 rval = setpgid(pid, pgid);
49
50 if (rval == -1) {
51 tst_brk_(file, lineno, TBROK | TERRNO,
52 "setpgid(%i, %i) failed", pid, pgid);
53 } else if (rval) {
54 tst_brk_(file, lineno, TBROK | TERRNO,
55 "Invalid setpgid(%i, %i) return value %d", pid, pgid,
56 rval);
57 }
58
59 return rval;
60 }
61
safe_getpgid(const char * file,const int lineno,pid_t pid)62 pid_t safe_getpgid(const char *file, const int lineno, pid_t pid)
63 {
64 pid_t pgid;
65
66 pgid = getpgid(pid);
67
68 if (pgid == -1) {
69 tst_brk_(file, lineno, TBROK | TERRNO, "getpgid(%i) failed",
70 pid);
71 } else if (pgid < 0) {
72 tst_brk_(file, lineno, TBROK | TERRNO,
73 "Invalid getpgid(%i) return value %d", pid, pgid);
74 }
75
76 return pgid;
77 }
78
safe_setgroups(const char * file,const int lineno,size_t size,const gid_t * list)79 int safe_setgroups(const char *file, const int lineno, size_t size, const gid_t *list)
80 {
81 int rval;
82
83 rval = setgroups(size, list);
84
85 if (rval == -1) {
86 tst_brk_(file, lineno, TBROK | TERRNO,
87 "setgroups(%zu, %p) failed", size, list);
88 } else if (rval) {
89 tst_brk_(file, lineno, TBROK | TERRNO,
90 "Invalid setgroups(%zu, %p) return value %d", size,
91 list, rval);
92 }
93
94 return rval;
95 }
96
safe_getgroups(const char * file,const int lineno,int size,gid_t list[])97 int safe_getgroups(const char *file, const int lineno, int size, gid_t list[])
98 {
99 int rval;
100
101 rval = getgroups(size, list);
102
103 if (rval == -1) {
104 tst_brk_(file, lineno, TBROK | TERRNO,
105 "getgroups(%i, %p)", size, list);
106 } else if (rval < 0) {
107 tst_brk_(file, lineno, TBROK | TERRNO,
108 "Invalid getgroups(%i, %p) return value %d", size,
109 list, rval);
110 }
111
112 return rval;
113 }
114
safe_personality(const char * filename,unsigned int lineno,unsigned long persona)115 int safe_personality(const char *filename, unsigned int lineno,
116 unsigned long persona)
117 {
118 int prev_persona = personality(persona);
119
120 if (prev_persona == -1) {
121 tst_brk_(filename, lineno, TBROK | TERRNO,
122 "persona(%ld) failed", persona);
123 } else if (prev_persona < 0) {
124 tst_brk_(filename, lineno, TBROK | TERRNO,
125 "Invalid persona(%ld) return value %d", persona,
126 prev_persona);
127 }
128
129 return prev_persona;
130 }
131
safe_pidfd_open(const char * file,const int lineno,pid_t pid,unsigned int flags)132 int safe_pidfd_open(const char *file, const int lineno, pid_t pid,
133 unsigned int flags)
134 {
135 int rval;
136
137 rval = pidfd_open(pid, flags);
138
139 if (rval == -1) {
140 tst_brk_(file, lineno, TBROK | TERRNO,
141 "pidfd_open(%i, %i) failed", pid, flags);
142 } else if (rval < 0) {
143 tst_brk_(file, lineno, TBROK | TERRNO,
144 "Invalid pidfd_open(%i, %i) return value %d",
145 pid, flags, rval);
146 }
147
148 return rval;
149 }
150
safe_setregid(const char * file,const int lineno,gid_t rgid,gid_t egid)151 int safe_setregid(const char *file, const int lineno,
152 gid_t rgid, gid_t egid)
153 {
154 int rval;
155
156 rval = setregid(rgid, egid);
157
158 if (rval == -1) {
159 tst_brk_(file, lineno, TBROK | TERRNO,
160 "setregid(%li, %li) failed", (long)rgid, (long)egid);
161 } else if (rval) {
162 tst_brk_(file, lineno, TBROK | TERRNO,
163 "Invalid setregid(%li, %li) return value %d",
164 (long)rgid, (long)egid, rval);
165 }
166
167 return rval;
168 }
169
safe_setreuid(const char * file,const int lineno,uid_t ruid,uid_t euid)170 int safe_setreuid(const char *file, const int lineno,
171 uid_t ruid, uid_t euid)
172 {
173 int rval;
174
175 rval = setreuid(ruid, euid);
176
177 if (rval == -1) {
178 tst_brk_(file, lineno, TBROK | TERRNO,
179 "setreuid(%li, %li) failed", (long)ruid, (long)euid);
180 } else if (rval) {
181 tst_brk_(file, lineno, TBROK | TERRNO,
182 "Invalid setreuid(%li, %li) return value %d",
183 (long)ruid, (long)euid, rval);
184 }
185
186 return rval;
187 }
188
safe_setresgid(const char * file,const int lineno,gid_t rgid,gid_t egid,gid_t sgid)189 int safe_setresgid(const char *file, const int lineno,
190 gid_t rgid, gid_t egid, gid_t sgid)
191 {
192 int ret;
193
194 ret = setresgid(rgid, egid, sgid);
195
196 if (ret == -1) {
197 tst_brk_(file, lineno, TBROK | TERRNO,
198 "setregid(%li, %li, %li) failed", (long)rgid,
199 (long)egid, (long)sgid);
200 } else if (ret) {
201 tst_brk_(file, lineno, TBROK | TERRNO,
202 "Invalid setregid(%li, %li, %li) return value %d",
203 (long)rgid, (long)egid, (long)sgid, ret);
204 }
205
206 return ret;
207 }
208
safe_setresuid(const char * file,const int lineno,uid_t ruid,uid_t euid,uid_t suid)209 int safe_setresuid(const char *file, const int lineno,
210 uid_t ruid, uid_t euid, uid_t suid)
211 {
212 int ret;
213
214 ret = setresuid(ruid, euid, suid);
215
216 if (ret == -1) {
217 tst_brk_(file, lineno, TBROK | TERRNO,
218 "setreuid(%li, %li, %li) failed", (long)ruid,
219 (long)euid, (long)suid);
220 } else if (ret) {
221 tst_brk_(file, lineno, TBROK | TERRNO,
222 "Invalid setreuid(%li, %li, %li) return value %d",
223 (long)ruid, (long)euid, (long)suid, ret);
224 }
225
226 return ret;
227 }
228
safe_sigaction(const char * file,const int lineno,int signum,const struct sigaction * act,struct sigaction * oldact)229 int safe_sigaction(const char *file, const int lineno,
230 int signum, const struct sigaction *act,
231 struct sigaction *oldact)
232 {
233 int rval;
234
235 rval = sigaction(signum, act, oldact);
236
237 if (rval == -1) {
238 tst_brk_(file, lineno, TBROK | TERRNO,
239 "sigaction(%s (%d), %p, %p) failed",
240 tst_strsig(signum), signum, act, oldact);
241 } else if (rval) {
242 tst_brk_(file, lineno, TBROK | TERRNO,
243 "Invalid sigaction(%s (%d), %p, %p) return value %d",
244 tst_strsig(signum), signum, act, oldact, rval);
245 }
246
247 return rval;
248 }
249
safe_sigaddset(const char * file,const int lineno,sigset_t * sigs,int signo)250 int safe_sigaddset(const char *file, const int lineno,
251 sigset_t *sigs, int signo)
252 {
253 int rval;
254
255 rval = sigaddset(sigs, signo);
256
257 if (rval == -1) {
258 tst_brk_(file, lineno, TBROK | TERRNO,
259 "sigaddset() %s (%i) failed", tst_strsig(signo),
260 signo);
261 } else if (rval) {
262 tst_brk_(file, lineno, TBROK | TERRNO,
263 "Invalid sigaddset() %s (%i) return value %d",
264 tst_strsig(signo), signo, rval);
265 }
266
267 return rval;
268 }
269
safe_sigdelset(const char * file,const int lineno,sigset_t * sigs,int signo)270 int safe_sigdelset(const char *file, const int lineno, sigset_t *sigs, int signo)
271 {
272 int rval;
273
274 rval = sigdelset(sigs, signo);
275
276 if (rval == -1) {
277 tst_brk_(file, lineno, TBROK | TERRNO,
278 "sigdelset() %s (%i) failed", tst_strsig(signo),
279 signo);
280 } else if (rval) {
281 tst_brk_(file, lineno, TBROK | TERRNO,
282 "Invalid sigdelset() %s (%i) return value %d",
283 tst_strsig(signo), signo, rval);
284 }
285
286 return rval;
287 }
288
safe_sigemptyset(const char * file,const int lineno,sigset_t * sigs)289 int safe_sigemptyset(const char *file, const int lineno, sigset_t *sigs)
290 {
291 int rval;
292
293 rval = sigemptyset(sigs);
294
295 if (rval == -1) {
296 tst_brk_(file, lineno, TBROK | TERRNO, "sigemptyset() failed");
297 } else if (rval) {
298 tst_brk_(file, lineno, TBROK | TERRNO,
299 "Invalid sigemptyset() return value %d", rval);
300 }
301
302 return rval;
303 }
304
safe_sigfillset(const char * file,const int lineno,sigset_t * sigs)305 int safe_sigfillset(const char *file, const int lineno,
306 sigset_t *sigs)
307 {
308 int rval;
309
310 rval = sigfillset(sigs);
311
312 if (rval == -1) {
313 tst_brk_(file, lineno, TBROK | TERRNO, "sigfillset() failed");
314 } else if (rval) {
315 tst_brk_(file, lineno, TBROK | TERRNO,
316 "Invalid sigfillset() return value %d", rval);
317 }
318
319 return rval;
320 }
321
strhow(int how)322 static const char *strhow(int how)
323 {
324 switch (how) {
325 case SIG_BLOCK:
326 return "SIG_BLOCK";
327 case SIG_UNBLOCK:
328 return "SIG_UNBLOCK";
329 case SIG_SETMASK:
330 return "SIG_SETMASK";
331 default:
332 return "???";
333 }
334 }
335
safe_sigprocmask(const char * file,const int lineno,int how,sigset_t * set,sigset_t * oldset)336 int safe_sigprocmask(const char *file, const int lineno,
337 int how, sigset_t *set, sigset_t *oldset)
338 {
339 int rval;
340
341 rval = sigprocmask(how, set, oldset);
342
343 if (rval == -1) {
344 tst_brk_(file, lineno, TBROK | TERRNO,
345 "sigprocmask(%s, %p, %p) failed", strhow(how), set,
346 oldset);
347 } else if (rval) {
348 tst_brk_(file, lineno, TBROK | TERRNO,
349 "Invalid sigprocmask(%s, %p, %p) return value %d",
350 strhow(how), set, oldset, rval);
351 }
352
353 return rval;
354 }
355
safe_sigwait(const char * file,const int lineno,sigset_t * set,int * sig)356 int safe_sigwait(const char *file, const int lineno, sigset_t *set, int *sig)
357 {
358 int rval;
359
360 rval = sigwait(set, sig);
361
362 if (rval > 0) {
363 errno = rval;
364 tst_brk_(file, lineno, TBROK | TERRNO,
365 "sigwait(%p, %p) failed", set, sig);
366 } else if (rval) {
367 tst_brk_(file, lineno, TBROK,
368 "Invalid sigwait(%p, %p) return value %d", set, sig,
369 rval);
370 }
371
372 return rval;
373 }
374
safe_getgrnam(const char * file,const int lineno,const char * name)375 struct group *safe_getgrnam(const char *file, const int lineno,
376 const char *name)
377 {
378 struct group *rval;
379
380 errno = 0;
381 rval = getgrnam(name);
382 if (rval == NULL) {
383 tst_brk_(file, lineno, TBROK | TERRNO,
384 "getgrnam(%s) failed", name);
385 }
386
387 return rval;
388 }
389
safe_getgrnam_fallback(const char * file,const int lineno,const char * name,const char * fallback)390 struct group *safe_getgrnam_fallback(const char *file, const int lineno,
391 const char *name, const char *fallback)
392 {
393 struct group *rval;
394
395 errno = 0;
396 rval = getgrnam(name);
397 if (rval == NULL) {
398 tst_res_(file, lineno, TINFO,
399 "getgrnam(%s) failed - try fallback %s",
400 name, fallback);
401 rval = safe_getgrnam(file, lineno, fallback);
402 }
403
404 return rval;
405 }
406
safe_getgrgid(const char * file,const int lineno,gid_t gid)407 struct group *safe_getgrgid(const char *file, const int lineno, gid_t gid)
408 {
409 struct group *rval;
410
411 errno = 0;
412 rval = getgrgid(gid);
413 if (rval == NULL) {
414 tst_brk_(file, lineno, TBROK | TERRNO,
415 "getgrgid(%li) failed", (long)gid);
416 }
417
418 return rval;
419 }
420
safe_chroot(const char * file,const int lineno,const char * path)421 int safe_chroot(const char *file, const int lineno, const char *path)
422 {
423 int rval;
424
425 rval = chroot(path);
426
427 if (rval == -1) {
428 tst_brk_(file, lineno, TBROK | TERRNO, "chroot(%s) failed",
429 path);
430 } else if (rval) {
431 tst_brk_(file, lineno, TBROK | TERRNO,
432 "Invalid chroot(%s) return value %d", path, rval);
433 }
434
435 return rval;
436 }
437
safe_unshare(const char * file,const int lineno,int flags)438 int safe_unshare(const char *file, const int lineno, int flags)
439 {
440 int res;
441
442 res = unshare(flags);
443
444 if (res == -1) {
445 if (errno == EINVAL) {
446 tst_brk_(file, lineno, TCONF | TERRNO,
447 "unshare(%d) unsupported", flags);
448 } else {
449 tst_brk_(file, lineno, TBROK | TERRNO,
450 "unshare(%d) failed", flags);
451 }
452 } else if (res) {
453 tst_brk_(file, lineno, TBROK | TERRNO,
454 "Invalid unshare(%d) return value %d", flags, res);
455 }
456
457 return res;
458 }
459
safe_setns(const char * file,const int lineno,int fd,int nstype)460 int safe_setns(const char *file, const int lineno, int fd, int nstype)
461 {
462 int ret;
463
464 ret = setns(fd, nstype);
465
466 if (ret == -1) {
467 tst_brk_(file, lineno, TBROK | TERRNO, "setns(%i, %i) failed",
468 fd, nstype);
469 } else if (ret) {
470 tst_brk_(file, lineno, TBROK | TERRNO,
471 "Invalid setns(%i, %i) return value %d", fd, nstype,
472 ret);
473 }
474
475 return ret;
476 }
477
tst_safe_ptrace(const char * file,const int lineno,int req,pid_t pid,void * addr,void * data)478 long tst_safe_ptrace(const char *file, const int lineno, int req, pid_t pid,
479 void *addr, void *data)
480 {
481 long ret;
482
483 errno = 0;
484 ret = ptrace(req, pid, addr, data);
485
486 if (ret == -1) {
487 tst_brk_(file, lineno, TBROK | TERRNO, "ptrace() failed");
488 } else if (ret) {
489 tst_brk_(file, lineno, TBROK | TERRNO,
490 "Invalid ptrace() return value %ld", ret);
491 }
492
493 return ret;
494 }
495
safe_pipe2(const char * file,const int lineno,int fildes[2],int flags)496 int safe_pipe2(const char *file, const int lineno, int fildes[2], int flags)
497 {
498 int ret;
499
500 ret = pipe2(fildes, flags);
501
502 if (ret == -1) {
503 tst_brk_(file, lineno, TBROK | TERRNO,
504 "pipe2({%d,%d}) failed with flag(%d)", fildes[0],
505 fildes[1], flags);
506 } else if (ret) {
507 tst_brk_(file, lineno, TBROK | TERRNO,
508 "Invalid pipe2({%d,%d}, %d) return value %d",
509 fildes[0], fildes[1], flags, ret);
510 }
511
512 return ret;
513 }
514
safe_dup(const char * file,const int lineno,int oldfd)515 int safe_dup(const char *file, const int lineno, int oldfd)
516 {
517 int rval;
518
519 rval = dup(oldfd);
520
521 if (rval == -1) {
522 tst_brk_(file, lineno, TBROK | TERRNO,
523 "dup(%i) failed", oldfd);
524 } else if (rval < 0) {
525 tst_brk_(file, lineno, TBROK | TERRNO,
526 "Invalid dup(%i) return value %d", oldfd, rval);
527 }
528
529 return rval;
530 }
531
safe_dup2(const char * file,const int lineno,int oldfd,int newfd)532 int safe_dup2(const char *file, const int lineno, int oldfd, int newfd)
533 {
534 int rval;
535
536 rval = dup2(oldfd, newfd);
537
538 if (rval == -1) {
539 tst_brk_(file, lineno, TBROK | TERRNO,
540 "dup2(%i, %i) failed", oldfd, newfd);
541 } else if (rval != newfd) {
542 tst_brk_(file, lineno, TBROK | TERRNO,
543 "Invalid dup2(%i, %i) return value %d",
544 oldfd, newfd, rval);
545 }
546
547 return rval;
548 }
549
safe_calloc(const char * file,const int lineno,size_t nmemb,size_t size)550 void *safe_calloc(const char *file, const int lineno, size_t nmemb, size_t size)
551 {
552 void *rval;
553
554 rval = calloc(nmemb, size);
555
556 if (rval == NULL) {
557 tst_brk_(file, lineno, TBROK | TERRNO,
558 "calloc(%zu, %zu) failed", nmemb, size);
559 }
560
561 return rval;
562 }
563
safe_realloc(const char * file,const int lineno,void * ptr,size_t size)564 void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size)
565 {
566 void *ret;
567
568 ret = realloc(ptr, size);
569
570 if (!ret) {
571 tst_brk_(file, lineno, TBROK | TERRNO,
572 "realloc(%p, %zu) failed", ptr, size);
573 }
574
575 return ret;
576 }
577
safe_signal(const char * file,const int lineno,int signum,sighandler_t handler)578 sighandler_t safe_signal(const char *file, const int lineno,
579 int signum, sighandler_t handler)
580 {
581 sighandler_t rval;
582
583 rval = signal(signum, handler);
584
585 if (rval == SIG_ERR) {
586 tst_brk_(file, lineno, TBROK | TERRNO,
587 "signal(%d,%p) failed",
588 signum, handler);
589 }
590
591 return rval;
592 }
593
safe_cmd(const char * file,const int lineno,const char * const argv[],const char * stdout_path,const char * stderr_path)594 void safe_cmd(const char *file, const int lineno, const char *const argv[],
595 const char *stdout_path, const char *stderr_path)
596 {
597 int rval;
598
599 switch ((rval = tst_cmd(argv, stdout_path, stderr_path,
600 TST_CMD_PASS_RETVAL | TST_CMD_TCONF_ON_MISSING))) {
601 case 0:
602 break;
603 default:
604 tst_brk_(file, lineno, TBROK, "%s failed (%d)", argv[0], rval);
605 }
606 }
607
safe_msync(const char * file,const int lineno,void * addr,size_t length,int flags)608 int safe_msync(const char *file, const int lineno, void *addr,
609 size_t length, int flags)
610 {
611 int rval;
612
613 rval = msync(addr, length, flags);
614
615 if (rval == -1) {
616 tst_brk_(file, lineno, TBROK | TERRNO,
617 "msync(%p, %zu, %d) failed", addr, length, flags);
618 } else if (rval) {
619 tst_brk_(file, lineno, TBROK | TERRNO,
620 "Invalid msync(%p, %zu, %d) return value %d",
621 addr, length, flags, rval);
622 }
623
624 return rval;
625 }
626
safe_print_file(const char * file,const int lineno,char * path)627 void safe_print_file(const char *file, const int lineno, char *path)
628 {
629 FILE *pfile;
630 char line[PATH_MAX];
631
632 tst_res(TINFO, "=== %s ===", path);
633
634 pfile = safe_fopen(file, lineno, NULL, path, "r");
635
636 while (fgets(line, sizeof(line), pfile))
637 fprintf(stderr, "%s", line);
638
639 safe_fclose(file, lineno, NULL, pfile);
640 }
641
safe_sscanf(const char * file,const int lineno,const char * restrict buffer,const char * restrict format,...)642 int safe_sscanf(const char *file, const int lineno, const char *restrict buffer, const char *restrict format, ...)
643 {
644 va_list args;
645
646 va_start(args, format);
647 int ret = vsscanf(buffer, format, args);
648
649 va_end(args);
650 int placeholders = tst_count_scanf_conversions(format);
651
652 if (ret == EOF)
653 tst_brk_(file, lineno, TBROK | TERRNO, "got EOF from sscanf()");
654
655 if (ret != placeholders)
656 tst_brk_(file, lineno, TBROK | TERRNO, "wrong number of conversion, expected %d, got %d", placeholders, ret);
657
658 return ret;
659 }
660
661 #define PROT_FLAG_STR(f) #f " | "
tst_prot_to_str(const int prot,char * buf)662 void tst_prot_to_str(const int prot, char *buf)
663 {
664 char *ptr = buf;
665
666 if (prot == PROT_NONE) {
667 strcpy(buf, "PROT_NONE");
668 return;
669 }
670
671 if (prot & PROT_READ) {
672 strcpy(ptr, PROT_FLAG_STR(PROT_READ));
673 ptr += sizeof(PROT_FLAG_STR(PROT_READ)) - 1;
674 }
675
676 if (prot & PROT_WRITE) {
677 strcpy(ptr, PROT_FLAG_STR(PROT_WRITE));
678 ptr += sizeof(PROT_FLAG_STR(PROT_WRITE)) - 1;
679 }
680
681 if (prot & PROT_EXEC) {
682 strcpy(ptr, PROT_FLAG_STR(PROT_EXEC));
683 ptr += sizeof(PROT_FLAG_STR(PROT_EXEC)) - 1;
684 }
685
686 if (buf != ptr)
687 ptr[-3] = 0;
688 }
689
safe_mprotect(const char * file,const int lineno,char * addr,size_t len,int prot)690 int safe_mprotect(const char *file, const int lineno,
691 char *addr, size_t len, int prot)
692 {
693 int rval;
694 char prot_buf[512];
695
696 tst_prot_to_str(prot, prot_buf);
697
698 tst_res_(file, lineno, TDEBUG,
699 "mprotect(%p, %zi, %s(%x))", addr, len, prot_buf, prot);
700
701 rval = mprotect(addr, len, prot);
702
703 if (rval == -1) {
704 tst_brk_(file, lineno, TBROK | TERRNO,
705 "mprotect(%p, %zi, %s(%x))", addr, len, prot_buf, prot);
706 } else if (rval) {
707 tst_brk_(file, lineno, TBROK | TERRNO,
708 "mprotect(%p, %zi, %s(%x)) return value %d",
709 addr, len, prot_buf, prot, rval);
710 }
711
712 return rval;
713 }
714
safe_prctl(const char * file,const int lineno,int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5)715 int safe_prctl(const char *file, const int lineno,
716 int option, unsigned long arg2, unsigned long arg3,
717 unsigned long arg4, unsigned long arg5)
718 {
719 int rval;
720
721 rval = prctl(option, arg2, arg3, arg4, arg5);
722 if (rval == -1) {
723 tst_brk_(file, lineno, TBROK | TERRNO,
724 "prctl(%d, %lu, %lu, %lu, %lu)",
725 option, arg2, arg3, arg4, arg5);
726 } else if (rval < 0) {
727 tst_brk_(file, lineno, TBROK | TERRNO,
728 "Invalid prctl(%d, %lu, %lu, %lu, %lu) return value %d",
729 option, arg2, arg3, arg4, arg5, rval);
730 }
731
732 return rval;
733 }
734
safe_readv(const char * file,const int lineno,char len_strict,int fildes,const struct iovec * iov,int iovcnt)735 ssize_t safe_readv(const char *file, const int lineno, char len_strict,
736 int fildes, const struct iovec *iov, int iovcnt)
737 {
738 ssize_t rval, nbyte;
739 int i;
740
741 for (i = 0, nbyte = 0; i < iovcnt; i++)
742 nbyte += iov[i].iov_len;
743
744 rval = readv(fildes, iov, iovcnt);
745
746 if (rval == -1 || (len_strict && rval != nbyte)) {
747 tst_brk_(file, lineno, TBROK | TERRNO,
748 "readv(%d,%p,%d) failed", fildes, iov, iovcnt);
749 } else if (rval < 0) {
750 tst_brk_(file, lineno, TBROK | TERRNO,
751 "Invalid readv(%d,%p,%d) return value %zd",
752 fildes, iov, iovcnt, rval);
753 }
754
755 return rval;
756 }
757
safe_symlinkat(const char * file,const int lineno,const char * oldpath,const int newdirfd,const char * newpath)758 int safe_symlinkat(const char *file, const int lineno,
759 const char *oldpath, const int newdirfd, const char *newpath)
760 {
761 int rval;
762
763 rval = symlinkat(oldpath, newdirfd, newpath);
764
765 if (rval == -1) {
766 tst_brk_(file, lineno, TBROK | TERRNO,
767 "symlinkat(%s,%d,%s) failed", oldpath, newdirfd, newpath);
768 } else if (rval) {
769 tst_brk_(file, lineno, TBROK | TERRNO,
770 "Invalid symlinkat(%s,%d,%s) return value %d", oldpath,
771 newdirfd, newpath, rval);
772 }
773
774 return rval;
775 }
776
safe_writev(const char * file,const int lineno,char len_strict,int fildes,const struct iovec * iov,int iovcnt)777 ssize_t safe_writev(const char *file, const int lineno, char len_strict,
778 int fildes, const struct iovec *iov, int iovcnt)
779 {
780 ssize_t rval, nbyte;
781 int i;
782
783 for (i = 0, nbyte = 0; i < iovcnt; i++)
784 nbyte += iov[i].iov_len;
785
786 rval = writev(fildes, iov, iovcnt);
787
788 if (rval == -1 || (len_strict && rval != nbyte)) {
789 tst_brk_(file, lineno, TBROK | TERRNO,
790 "writev(%d,%p,%d) failed", fildes, iov, iovcnt);
791 } else if (rval < 0) {
792 tst_brk_(file, lineno, TBROK | TERRNO,
793 "Invalid writev(%d,%p,%d) return value %zd",
794 fildes, iov, iovcnt, rval);
795 }
796
797 return rval;
798 }
799
safe_ptsname(const char * const file,const int lineno,int masterfd)800 char *safe_ptsname(const char *const file, const int lineno, int masterfd)
801 {
802 char *name;
803
804 name = ptsname(masterfd);
805
806 if (!name) {
807 tst_brk_(file, lineno, TBROK | TERRNO,
808 "ptsname(%d) failed", masterfd);
809 }
810
811 return name;
812 }
813