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