• 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  */
5 
6 #define _GNU_SOURCE
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <errno.h>
10 #include <sched.h>
11 #include <sys/ptrace.h>
12 #include "config.h"
13 #ifdef HAVE_SYS_FANOTIFY_H
14 # include <sys/fanotify.h>
15 #endif
16 #define TST_NO_DEFAULT_MAIN
17 #include "tst_test.h"
18 #include "lapi/setns.h"
19 #include "tst_safe_macros.h"
20 #include "lapi/personality.h"
21 #include "lapi/pidfd.h"
22 
safe_access(const char * file,const int lineno,const char * pathname,int mode)23 int safe_access(const char *file, const int lineno,
24 	    const char *pathname, int mode)
25 {
26 	int rval;
27 
28 	rval = access(pathname, mode);
29 
30 	if (rval == -1) {
31 		tst_brk_(file, lineno, TBROK | TERRNO,
32 			"access(%s,%d) failed", pathname, mode);
33 	} else if (rval) {
34 		tst_brk_(file, lineno, TBROK | TERRNO,
35 			"Invalid access(%s,%d) return value %d", pathname,
36 			mode, rval);
37 	}
38 
39 	return rval;
40 }
41 
safe_setpgid(const char * file,const int lineno,pid_t pid,pid_t pgid)42 int safe_setpgid(const char *file, const int lineno, pid_t pid, pid_t pgid)
43 {
44 	int rval;
45 
46 	rval = setpgid(pid, pgid);
47 
48 	if (rval == -1) {
49 		tst_brk_(file, lineno, TBROK | TERRNO,
50 			"setpgid(%i, %i) failed", pid, pgid);
51 	} else if (rval) {
52 		tst_brk_(file, lineno, TBROK | TERRNO,
53 			"Invalid setpgid(%i, %i) return value %d", pid, pgid,
54 			rval);
55 	}
56 
57 	return rval;
58 }
59 
safe_getpgid(const char * file,const int lineno,pid_t pid)60 pid_t safe_getpgid(const char *file, const int lineno, pid_t pid)
61 {
62 	pid_t pgid;
63 
64 	pgid = getpgid(pid);
65 
66 	if (pgid == -1) {
67 		tst_brk_(file, lineno, TBROK | TERRNO, "getpgid(%i) failed",
68 			pid);
69 	} else if (pgid < 0) {
70 		tst_brk_(file, lineno, TBROK | TERRNO,
71 			"Invalid getpgid(%i) return value %d", pid, pgid);
72 	}
73 
74 	return pgid;
75 }
76 
safe_setgroups(const char * file,const int lineno,size_t size,const gid_t * list)77 int safe_setgroups(const char *file, const int lineno, size_t size, const gid_t *list)
78 {
79 	int rval;
80 
81 	rval = setgroups(size, list);
82 
83 	if (rval == -1) {
84 		tst_brk_(file, lineno, TBROK | TERRNO,
85 			"setgroups(%zu, %p) failed", size, list);
86 	} else if (rval) {
87 		tst_brk_(file, lineno, TBROK | TERRNO,
88 			"Invalid setgroups(%zu, %p) return value %d", size,
89 			list, rval);
90 	}
91 
92 	return rval;
93 }
94 
safe_getgroups(const char * file,const int lineno,int size,gid_t list[])95 int safe_getgroups(const char *file, const int lineno, int size, gid_t list[])
96 {
97 	int rval;
98 
99 	rval = getgroups(size, list);
100 
101 	if (rval == -1) {
102 		tst_brk_(file, lineno, TBROK | TERRNO,
103 			"getgroups(%i, %p)", size, list);
104 	} else if (rval < 0) {
105 		tst_brk_(file, lineno, TBROK | TERRNO,
106 			"Invalid getgroups(%i, %p) return value %d", size,
107 			list, rval);
108 	}
109 
110 	return rval;
111 }
112 
safe_personality(const char * filename,unsigned int lineno,unsigned long persona)113 int safe_personality(const char *filename, unsigned int lineno,
114 		    unsigned long persona)
115 {
116 	int prev_persona = personality(persona);
117 
118 	if (prev_persona == -1) {
119 		tst_brk_(filename, lineno, TBROK | TERRNO,
120 			 "persona(%ld) failed", persona);
121 	} else if (prev_persona < 0) {
122 		tst_brk_(filename, lineno, TBROK | TERRNO,
123 			 "Invalid persona(%ld) return value %d", persona,
124 			 prev_persona);
125 	}
126 
127 	return prev_persona;
128 }
129 
safe_pidfd_open(const char * file,const int lineno,pid_t pid,unsigned int flags)130 int safe_pidfd_open(const char *file, const int lineno, pid_t pid,
131 		   unsigned int flags)
132 {
133 	int rval;
134 
135 	rval = pidfd_open(pid, flags);
136 
137 	if (rval == -1) {
138 		tst_brk_(file, lineno, TBROK | TERRNO,
139 			 "pidfd_open(%i, %i) failed", pid, flags);
140 	} else if (rval < 0) {
141 		tst_brk_(file, lineno, TBROK | TERRNO,
142 			 "Invalid pidfd_open(%i, %i) return value %d",
143 			 pid, flags, rval);
144 	}
145 
146 	return rval;
147 }
148 
safe_setregid(const char * file,const int lineno,gid_t rgid,gid_t egid)149 int safe_setregid(const char *file, const int lineno,
150 		  gid_t rgid, gid_t egid)
151 {
152 	int rval;
153 
154 	rval = setregid(rgid, egid);
155 
156 	if (rval == -1) {
157 		tst_brk_(file, lineno, TBROK | TERRNO,
158 			 "setregid(%li, %li) failed", (long)rgid, (long)egid);
159 	} else if (rval) {
160 		tst_brk_(file, lineno, TBROK | TERRNO,
161 			 "Invalid setregid(%li, %li) return value %d",
162 			 (long)rgid, (long)egid, rval);
163 	}
164 
165 	return rval;
166 }
167 
safe_setreuid(const char * file,const int lineno,uid_t ruid,uid_t euid)168 int safe_setreuid(const char *file, const int lineno,
169 		  uid_t ruid, uid_t euid)
170 {
171 	int rval;
172 
173 	rval = setreuid(ruid, euid);
174 
175 	if (rval == -1) {
176 		tst_brk_(file, lineno, TBROK | TERRNO,
177 			 "setreuid(%li, %li) failed", (long)ruid, (long)euid);
178 	} else if (rval) {
179 		tst_brk_(file, lineno, TBROK | TERRNO,
180 			 "Invalid setreuid(%li, %li) return value %d",
181 			 (long)ruid, (long)euid, rval);
182 	}
183 
184 	return rval;
185 }
186 
safe_setresgid(const char * file,const int lineno,gid_t rgid,gid_t egid,gid_t sgid)187 int safe_setresgid(const char *file, const int lineno,
188 	gid_t rgid, gid_t egid, gid_t sgid)
189 {
190 	int ret;
191 
192 	ret = setresgid(rgid, egid, sgid);
193 
194 	if (ret == -1) {
195 		tst_brk_(file, lineno, TBROK | TERRNO,
196 			"setregid(%li, %li, %li) failed", (long)rgid,
197 			(long)egid, (long)sgid);
198 	} else if (ret) {
199 		tst_brk_(file, lineno, TBROK | TERRNO,
200 			"Invalid setregid(%li, %li, %li) return value %d",
201 			(long)rgid, (long)egid, (long)sgid, ret);
202 	}
203 
204 	return ret;
205 }
206 
safe_setresuid(const char * file,const int lineno,uid_t ruid,uid_t euid,uid_t suid)207 int safe_setresuid(const char *file, const int lineno,
208 	uid_t ruid, uid_t euid, uid_t suid)
209 {
210 	int ret;
211 
212 	ret = setresuid(ruid, euid, suid);
213 
214 	if (ret == -1) {
215 		tst_brk_(file, lineno, TBROK | TERRNO,
216 			"setreuid(%li, %li, %li) failed", (long)ruid,
217 			(long)euid, (long)suid);
218 	} else if (ret) {
219 		tst_brk_(file, lineno, TBROK | TERRNO,
220 			"Invalid setreuid(%li, %li, %li) return value %d",
221 			(long)ruid, (long)euid, (long)suid, ret);
222 	}
223 
224 	return ret;
225 }
226 
safe_sigaction(const char * file,const int lineno,int signum,const struct sigaction * act,struct sigaction * oldact)227 int safe_sigaction(const char *file, const int lineno,
228                    int signum, const struct sigaction *act,
229                    struct sigaction *oldact)
230 {
231 	int rval;
232 
233 	rval = sigaction(signum, act, oldact);
234 
235 	if (rval == -1) {
236 		tst_brk_(file, lineno, TBROK | TERRNO,
237 			"sigaction(%s (%d), %p, %p) failed",
238 			tst_strsig(signum), signum, act, oldact);
239 	} else if (rval) {
240 		tst_brk_(file, lineno, TBROK | TERRNO,
241 			"Invalid sigaction(%s (%d), %p, %p) return value %d",
242 			tst_strsig(signum), signum, act, oldact, rval);
243 	}
244 
245 	return rval;
246 }
247 
safe_sigaddset(const char * file,const int lineno,sigset_t * sigs,int signo)248 int safe_sigaddset(const char *file, const int lineno,
249                     sigset_t *sigs, int signo)
250 {
251 	int rval;
252 
253 	rval = sigaddset(sigs, signo);
254 
255 	if (rval == -1) {
256 		tst_brk_(file, lineno, TBROK | TERRNO,
257 			"sigaddset() %s (%i) failed", tst_strsig(signo),
258 			signo);
259 	} else if (rval) {
260 		tst_brk_(file, lineno, TBROK | TERRNO,
261 			"Invalid sigaddset() %s (%i) return value %d",
262 			tst_strsig(signo), signo, rval);
263 	}
264 
265 	return rval;
266 }
267 
safe_sigdelset(const char * file,const int lineno,sigset_t * sigs,int signo)268 int safe_sigdelset(const char *file, const int lineno,
269                     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,
289                       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,
357                   sigset_t *set, int *sig)
358 {
359 	int rval;
360 
361 	rval = sigwait(set, sig);
362 
363 	if (rval > 0) {
364 		errno = rval;
365 		tst_brk_(file, lineno, TBROK | TERRNO,
366 			"sigwait(%p, %p) failed", set, sig);
367 	} else if (rval) {
368 		tst_brk_(file, lineno, TBROK,
369 			"Invalid sigwait(%p, %p) return value %d", set, sig,
370 			rval);
371 	}
372 
373 	return rval;
374 }
375 
safe_getgrnam(const char * file,const int lineno,const char * name)376 struct group *safe_getgrnam(const char *file, const int lineno,
377 			    const char *name)
378 {
379 	struct group *rval;
380 
381 	errno = 0;
382 	rval = getgrnam(name);
383 	if (rval == NULL) {
384 		tst_brk_(file, lineno, TBROK | TERRNO,
385 			"getgrnam(%s) failed", name);
386 	}
387 
388 	return rval;
389 }
390 
safe_getgrnam_fallback(const char * file,const int lineno,const char * name,const char * fallback)391 struct group *safe_getgrnam_fallback(const char *file, const int lineno,
392 				     const char *name, const char *fallback)
393 {
394 	struct group *rval;
395 
396 	errno = 0;
397 	rval = getgrnam(name);
398 	if (rval == NULL) {
399 		tst_res_(file, lineno, TINFO,
400 			 "getgrnam(%s) failed - try fallback %s",
401 			 name, fallback);
402 		rval = safe_getgrnam(file, lineno, fallback);
403 	}
404 
405 	return rval;
406 }
407 
safe_getgrgid(const char * file,const int lineno,gid_t gid)408 struct group *safe_getgrgid(const char *file, const int lineno, gid_t gid)
409 {
410 	struct group *rval;
411 
412 	errno = 0;
413 	rval = getgrgid(gid);
414 	if (rval == NULL) {
415 		tst_brk_(file, lineno, TBROK | TERRNO,
416 			"getgrgid(%li) failed", (long)gid);
417 	}
418 
419 	return rval;
420 }
421 
safe_chroot(const char * file,const int lineno,const char * path)422 int safe_chroot(const char *file, const int lineno, const char *path)
423 {
424 	int rval;
425 
426 	rval = chroot(path);
427 
428 	if (rval == -1) {
429 		tst_brk_(file, lineno, TBROK | TERRNO, "chroot(%s) failed",
430 			path);
431 	} else if (rval) {
432 		tst_brk_(file, lineno, TBROK | TERRNO,
433 			 "Invalid chroot(%s) return value %d", path, rval);
434 	}
435 
436 	return rval;
437 }
438 
safe_unshare(const char * file,const int lineno,int flags)439 int safe_unshare(const char *file, const int lineno, int flags)
440 {
441 	int res;
442 
443 	res = unshare(flags);
444 
445 	if (res == -1) {
446 		if (errno == EINVAL) {
447 			tst_brk_(file, lineno, TCONF | TERRNO,
448 				 "unshare(%d) unsupported", flags);
449 		} else {
450 			tst_brk_(file, lineno, TBROK | TERRNO,
451 				 "unshare(%d) failed", flags);
452 		}
453 	} else if (res) {
454 		tst_brk_(file, lineno, TBROK | TERRNO,
455 			 "Invalid unshare(%d) return value %d", flags, res);
456 	}
457 
458 	return res;
459 }
460 
safe_setns(const char * file,const int lineno,int fd,int nstype)461 int safe_setns(const char *file, const int lineno, int fd, int nstype)
462 {
463 	int ret;
464 
465 	ret = setns(fd, nstype);
466 
467 	if (ret == -1) {
468 		tst_brk_(file, lineno, TBROK | TERRNO, "setns(%i, %i) failed",
469 			fd, nstype);
470 	} else if (ret) {
471 		tst_brk_(file, lineno, TBROK | TERRNO,
472 			"Invalid setns(%i, %i) return value %d", fd, nstype,
473 			ret);
474 	}
475 
476 	return ret;
477 }
478 
tst_safe_ptrace(const char * file,const int lineno,int req,pid_t pid,void * addr,void * data)479 long tst_safe_ptrace(const char *file, const int lineno, int req, pid_t pid,
480 	void *addr, void *data)
481 {
482 	long ret;
483 
484 	errno = 0;
485 	ret = ptrace(req, pid, addr, data);
486 
487 	if (ret == -1) {
488 		tst_brk_(file, lineno, TBROK | TERRNO, "ptrace() failed");
489 	} else if (ret) {
490 		tst_brk_(file, lineno, TBROK | TERRNO,
491 			"Invalid ptrace() return value %ld", ret);
492 	}
493 
494 	return ret;
495 }
496 
safe_pipe2(const char * file,const int lineno,int fildes[2],int flags)497 int safe_pipe2(const char *file, const int lineno, int fildes[2], int flags)
498 {
499 	int ret;
500 
501 	ret = pipe2(fildes, flags);
502 
503 	if (ret == -1) {
504 		tst_brk_(file, lineno, TBROK | TERRNO,
505 			"pipe2({%d,%d}) failed with flag(%d)", fildes[0],
506 			fildes[1], flags);
507 	} else if (ret) {
508 		tst_brk_(file, lineno, TBROK | TERRNO,
509 			"Invalid pipe2({%d,%d}, %d) return value %d",
510 			fildes[0], fildes[1], flags, ret);
511 	}
512 
513 	return ret;
514 }
515 
safe_dup(const char * file,const int lineno,int oldfd)516 int safe_dup(const char *file, const int lineno, int oldfd)
517 {
518 	int rval;
519 
520 	rval = dup(oldfd);
521 
522 	if (rval == -1) {
523 		tst_brk_(file, lineno, TBROK | TERRNO,
524 			"dup(%i) failed", oldfd);
525 	} else if (rval < 0) {
526 		tst_brk_(file, lineno, TBROK | TERRNO,
527 			"Invalid dup(%i) return value %d", oldfd, rval);
528 	}
529 
530 	return rval;
531 }
532 
safe_dup2(const char * file,const int lineno,int oldfd,int newfd)533 int safe_dup2(const char *file, const int lineno, int oldfd, int newfd)
534 {
535 	int rval;
536 
537 	rval = dup2(oldfd, newfd);
538 
539 	if (rval == -1) {
540 		tst_brk_(file, lineno, TBROK | TERRNO,
541 			 "dup2(%i, %i) failed", oldfd, newfd);
542 	} else if (rval != newfd) {
543 		tst_brk_(file, lineno, TBROK | TERRNO,
544 			 "Invalid dup2(%i, %i) return value %d",
545 			 oldfd, newfd, rval);
546 	}
547 
548 	return rval;
549 }
550 
safe_realloc(const char * file,const int lineno,void * ptr,size_t size)551 void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size)
552 {
553 	void *ret;
554 
555 	ret = realloc(ptr, size);
556 
557 	if (!ret) {
558 		tst_brk_(file, lineno, TBROK | TERRNO,
559 			"realloc(%p, %zu) failed", ptr, size);
560 	}
561 
562 	return ret;
563 }
564 
safe_signal(const char * file,const int lineno,int signum,sighandler_t handler)565 sighandler_t safe_signal(const char *file, const int lineno,
566 	int signum, sighandler_t handler)
567 {
568 	sighandler_t rval;
569 
570 	rval = signal(signum, handler);
571 
572 	if (rval == SIG_ERR) {
573 		tst_brk_(file, lineno, TBROK | TERRNO,
574 			"signal(%d,%p) failed",
575 			signum, handler);
576 	}
577 
578 	return rval;
579 }
580 
safe_cmd(const char * file,const int lineno,const char * const argv[],const char * stdout_path,const char * stderr_path)581 void safe_cmd(const char *file, const int lineno, const char *const argv[],
582 	const char *stdout_path, const char *stderr_path)
583 {
584 	int rval;
585 
586 	switch ((rval = tst_cmd(argv, stdout_path, stderr_path,
587 		TST_CMD_PASS_RETVAL | TST_CMD_TCONF_ON_MISSING))) {
588 	case 0:
589 		break;
590 	default:
591 		tst_brk_(file, lineno, TBROK, "%s failed (%d)", argv[0], rval);
592 	}
593 }
594