• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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