• 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 
safe_setpgid(const char * file,const int lineno,pid_t pid,pid_t pgid)22 int safe_setpgid(const char *file, const int lineno, pid_t pid, pid_t pgid)
23 {
24 	int rval;
25 
26 	rval = setpgid(pid, pgid);
27 
28 	if (rval == -1) {
29 		tst_brk_(file, lineno, TBROK | TERRNO,
30 			"setpgid(%i, %i) failed", pid, pgid);
31 	} else if (rval) {
32 		tst_brk_(file, lineno, TBROK | TERRNO,
33 			"Invalid setpgid(%i, %i) return value %d", pid, pgid,
34 			rval);
35 	}
36 
37 	return rval;
38 }
39 
safe_getpgid(const char * file,const int lineno,pid_t pid)40 pid_t safe_getpgid(const char *file, const int lineno, pid_t pid)
41 {
42 	pid_t pgid;
43 
44 	pgid = getpgid(pid);
45 
46 	if (pgid == -1) {
47 		tst_brk_(file, lineno, TBROK | TERRNO, "getpgid(%i) failed",
48 			pid);
49 	} else if (pgid < 0) {
50 		tst_brk_(file, lineno, TBROK | TERRNO,
51 			"Invalid getpgid(%i) return value %d", pid, pgid);
52 	}
53 
54 	return pgid;
55 }
56 
safe_setgroups(const char * file,const int lineno,size_t size,const gid_t * list)57 int safe_setgroups(const char *file, const int lineno, size_t size, const gid_t *list)
58 {
59 	int rval;
60 
61 	rval = setgroups(size, list);
62 
63 	if (rval == -1) {
64 		tst_brk_(file, lineno, TBROK | TERRNO,
65 			"setgroups(%zu, %p) failed", size, list);
66 	} else if (rval) {
67 		tst_brk_(file, lineno, TBROK | TERRNO,
68 			"Invalid setgroups(%zu, %p) return value %d", size,
69 			list, rval);
70 	}
71 
72 	return rval;
73 }
74 
safe_getgroups(const char * file,const int lineno,int size,gid_t list[])75 int safe_getgroups(const char *file, const int lineno, int size, gid_t list[])
76 {
77 	int rval;
78 
79 	rval = getgroups(size, list);
80 
81 	if (rval == -1) {
82 		tst_brk_(file, lineno, TBROK | TERRNO,
83 			"getgroups(%i, %p)", size, list);
84 	} else if (rval < 0) {
85 		tst_brk_(file, lineno, TBROK | TERRNO,
86 			"Invalid getgroups(%i, %p) return value %d", size,
87 			list, rval);
88 	}
89 
90 	return rval;
91 }
92 
safe_personality(const char * filename,unsigned int lineno,unsigned long persona)93 int safe_personality(const char *filename, unsigned int lineno,
94 		    unsigned long persona)
95 {
96 	int prev_persona = personality(persona);
97 
98 	if (prev_persona == -1) {
99 		tst_brk_(filename, lineno, TBROK | TERRNO,
100 			 "persona(%ld) failed", persona);
101 	} else if (prev_persona < 0) {
102 		tst_brk_(filename, lineno, TBROK | TERRNO,
103 			 "Invalid persona(%ld) return value %d", persona,
104 			 prev_persona);
105 	}
106 
107 	return prev_persona;
108 }
109 
safe_setregid(const char * file,const int lineno,gid_t rgid,gid_t egid)110 int safe_setregid(const char *file, const int lineno,
111 		  gid_t rgid, gid_t egid)
112 {
113 	int rval;
114 
115 	rval = setregid(rgid, egid);
116 
117 	if (rval == -1) {
118 		tst_brk_(file, lineno, TBROK | TERRNO,
119 			 "setregid(%li, %li) failed", (long)rgid, (long)egid);
120 	} else if (rval) {
121 		tst_brk_(file, lineno, TBROK | TERRNO,
122 			 "Invalid setregid(%li, %li) return value %d",
123 			 (long)rgid, (long)egid, rval);
124 	}
125 
126 	return rval;
127 }
128 
safe_setreuid(const char * file,const int lineno,uid_t ruid,uid_t euid)129 int safe_setreuid(const char *file, const int lineno,
130 		  uid_t ruid, uid_t euid)
131 {
132 	int rval;
133 
134 	rval = setreuid(ruid, euid);
135 
136 	if (rval == -1) {
137 		tst_brk_(file, lineno, TBROK | TERRNO,
138 			 "setreuid(%li, %li) failed", (long)ruid, (long)euid);
139 	} else if (rval) {
140 		tst_brk_(file, lineno, TBROK | TERRNO,
141 			 "Invalid setreuid(%li, %li) return value %d",
142 			 (long)ruid, (long)euid, rval);
143 	}
144 
145 	return rval;
146 }
147 
safe_setresgid(const char * file,const int lineno,gid_t rgid,gid_t egid,gid_t sgid)148 int safe_setresgid(const char *file, const int lineno,
149 	gid_t rgid, gid_t egid, gid_t sgid)
150 {
151 	int ret;
152 
153 	ret = setresgid(rgid, egid, sgid);
154 
155 	if (ret == -1) {
156 		tst_brk_(file, lineno, TBROK | TERRNO,
157 			"setregid(%li, %li, %li) failed", (long)rgid,
158 			(long)egid, (long)sgid);
159 	} else if (ret) {
160 		tst_brk_(file, lineno, TBROK | TERRNO,
161 			"Invalid setregid(%li, %li, %li) return value %d",
162 			(long)rgid, (long)egid, (long)sgid, ret);
163 	}
164 
165 	return ret;
166 }
167 
safe_setresuid(const char * file,const int lineno,uid_t ruid,uid_t euid,uid_t suid)168 int safe_setresuid(const char *file, const int lineno,
169 	uid_t ruid, uid_t euid, uid_t suid)
170 {
171 	int ret;
172 
173 	ret = setresuid(ruid, euid, suid);
174 
175 	if (ret == -1) {
176 		tst_brk_(file, lineno, TBROK | TERRNO,
177 			"setreuid(%li, %li, %li) failed", (long)ruid,
178 			(long)euid, (long)suid);
179 	} else if (ret) {
180 		tst_brk_(file, lineno, TBROK | TERRNO,
181 			"Invalid setreuid(%li, %li, %li) return value %d",
182 			(long)ruid, (long)euid, (long)suid, ret);
183 	}
184 
185 	return ret;
186 }
187 
safe_sigaction(const char * file,const int lineno,int signum,const struct sigaction * act,struct sigaction * oldact)188 int safe_sigaction(const char *file, const int lineno,
189                    int signum, const struct sigaction *act,
190                    struct sigaction *oldact)
191 {
192 	int rval;
193 
194 	rval = sigaction(signum, act, oldact);
195 
196 	if (rval == -1) {
197 		tst_brk_(file, lineno, TBROK | TERRNO,
198 			"sigaction(%s (%d), %p, %p) failed",
199 			tst_strsig(signum), signum, act, oldact);
200 	} else if (rval) {
201 		tst_brk_(file, lineno, TBROK | TERRNO,
202 			"Invalid sigaction(%s (%d), %p, %p) return value %d",
203 			tst_strsig(signum), signum, act, oldact, rval);
204 	}
205 
206 	return rval;
207 }
208 
safe_sigaddset(const char * file,const int lineno,sigset_t * sigs,int signo)209 int safe_sigaddset(const char *file, const int lineno,
210                     sigset_t *sigs, int signo)
211 {
212 	int rval;
213 
214 	rval = sigaddset(sigs, signo);
215 
216 	if (rval == -1) {
217 		tst_brk_(file, lineno, TBROK | TERRNO,
218 			"sigaddset() %s (%i) failed", tst_strsig(signo),
219 			signo);
220 	} else if (rval) {
221 		tst_brk_(file, lineno, TBROK | TERRNO,
222 			"Invalid sigaddset() %s (%i) return value %d",
223 			tst_strsig(signo), signo, rval);
224 	}
225 
226 	return rval;
227 }
228 
safe_sigdelset(const char * file,const int lineno,sigset_t * sigs,int signo)229 int safe_sigdelset(const char *file, const int lineno,
230                     sigset_t *sigs, int signo)
231 {
232 	int rval;
233 
234 	rval = sigdelset(sigs, signo);
235 
236 	if (rval == -1) {
237 		tst_brk_(file, lineno, TBROK | TERRNO,
238 			"sigdelset() %s (%i) failed", tst_strsig(signo),
239 			signo);
240 	} else if (rval) {
241 		tst_brk_(file, lineno, TBROK | TERRNO,
242 			"Invalid sigdelset() %s (%i) return value %d",
243 			tst_strsig(signo), signo, rval);
244 	}
245 
246 	return rval;
247 }
248 
safe_sigemptyset(const char * file,const int lineno,sigset_t * sigs)249 int safe_sigemptyset(const char *file, const int lineno,
250                       sigset_t *sigs)
251 {
252 	int rval;
253 
254 	rval = sigemptyset(sigs);
255 
256 	if (rval == -1) {
257 		tst_brk_(file, lineno, TBROK | TERRNO, "sigemptyset() failed");
258 	} else if (rval) {
259 		tst_brk_(file, lineno, TBROK | TERRNO,
260 			"Invalid sigemptyset() return value %d", rval);
261 	}
262 
263 	return rval;
264 }
265 
safe_sigfillset(const char * file,const int lineno,sigset_t * sigs)266 int safe_sigfillset(const char *file, const int lineno,
267 		     sigset_t *sigs)
268 {
269 	int rval;
270 
271 	rval = sigfillset(sigs);
272 
273 	if (rval == -1) {
274 		tst_brk_(file, lineno, TBROK | TERRNO, "sigfillset() failed");
275 	} else if (rval) {
276 		tst_brk_(file, lineno, TBROK | TERRNO,
277 			"Invalid sigfillset() return value %d", rval);
278 	}
279 
280 	return rval;
281 }
282 
strhow(int how)283 static const char *strhow(int how)
284 {
285 	switch (how) {
286 	case SIG_BLOCK:
287 		return "SIG_BLOCK";
288 	case SIG_UNBLOCK:
289 		return "SIG_UNBLOCK";
290 	case SIG_SETMASK:
291 		return "SIG_SETMASK";
292 	default:
293 		return "???";
294 	}
295 }
296 
safe_sigprocmask(const char * file,const int lineno,int how,sigset_t * set,sigset_t * oldset)297 int safe_sigprocmask(const char *file, const int lineno,
298                       int how, sigset_t *set, sigset_t *oldset)
299 {
300 	int rval;
301 
302 	rval = sigprocmask(how, set, oldset);
303 
304 	if (rval == -1) {
305 		tst_brk_(file, lineno, TBROK | TERRNO,
306 			"sigprocmask(%s, %p, %p) failed", strhow(how), set,
307 			oldset);
308 	} else if (rval) {
309 		tst_brk_(file, lineno, TBROK | TERRNO,
310 			"Invalid sigprocmask(%s, %p, %p) return value %d",
311 			strhow(how), set, oldset, rval);
312 	}
313 
314 	return rval;
315 }
316 
safe_sigwait(const char * file,const int lineno,sigset_t * set,int * sig)317 int safe_sigwait(const char *file, const int lineno,
318                   sigset_t *set, int *sig)
319 {
320 	int rval;
321 
322 	rval = sigwait(set, sig);
323 
324 	if (rval > 0) {
325 		errno = rval;
326 		tst_brk_(file, lineno, TBROK | TERRNO,
327 			"sigwait(%p, %p) failed", set, sig);
328 	} else if (rval) {
329 		tst_brk_(file, lineno, TBROK,
330 			"Invalid sigwait(%p, %p) return value %d", set, sig,
331 			rval);
332 	}
333 
334 	return rval;
335 }
336 
safe_getgrnam(const char * file,const int lineno,const char * name)337 struct group *safe_getgrnam(const char *file, const int lineno,
338 			    const char *name)
339 {
340 	struct group *rval;
341 
342 	errno = 0;
343 	rval = getgrnam(name);
344 	if (rval == NULL) {
345 		tst_brk_(file, lineno, TBROK | TERRNO,
346 			"getgrnam(%s) failed", name);
347 	}
348 
349 	return rval;
350 }
351 
safe_getgrnam_fallback(const char * file,const int lineno,const char * name,const char * fallback)352 struct group *safe_getgrnam_fallback(const char *file, const int lineno,
353 				     const char *name, const char *fallback)
354 {
355 	struct group *rval;
356 
357 	errno = 0;
358 	rval = getgrnam(name);
359 	if (rval == NULL) {
360 		tst_res_(file, lineno, TINFO,
361 			 "getgrnam(%s) failed - try fallback %s",
362 			 name, fallback);
363 		rval = safe_getgrnam(file, lineno, fallback);
364 	}
365 
366 	return rval;
367 }
368 
safe_getgrgid(const char * file,const int lineno,gid_t gid)369 struct group *safe_getgrgid(const char *file, const int lineno, gid_t gid)
370 {
371 	struct group *rval;
372 
373 	errno = 0;
374 	rval = getgrgid(gid);
375 	if (rval == NULL) {
376 		tst_brk_(file, lineno, TBROK | TERRNO,
377 			"getgrgid(%li) failed", (long)gid);
378 	}
379 
380 	return rval;
381 }
382 
safe_chroot(const char * file,const int lineno,const char * path)383 int safe_chroot(const char *file, const int lineno, const char *path)
384 {
385 	int rval;
386 
387 	rval = chroot(path);
388 
389 	if (rval == -1) {
390 		tst_brk_(file, lineno, TBROK | TERRNO, "chroot(%s) failed",
391 			path);
392 	} else if (rval) {
393 		tst_brk_(file, lineno, TBROK | TERRNO,
394 			 "Invalid chroot(%s) return value %d", path, rval);
395 	}
396 
397 	return rval;
398 }
399 
safe_unshare(const char * file,const int lineno,int flags)400 int safe_unshare(const char *file, const int lineno, int flags)
401 {
402 	int res;
403 
404 	res = unshare(flags);
405 
406 	if (res == -1) {
407 		if (errno == EINVAL) {
408 			tst_brk_(file, lineno, TCONF | TERRNO,
409 				 "unshare(%d) unsupported", flags);
410 		} else {
411 			tst_brk_(file, lineno, TBROK | TERRNO,
412 				 "unshare(%d) failed", flags);
413 		}
414 	} else if (res) {
415 		tst_brk_(file, lineno, TBROK | TERRNO,
416 			 "Invalid unshare(%d) return value %d", flags, res);
417 	}
418 
419 	return res;
420 }
421 
safe_setns(const char * file,const int lineno,int fd,int nstype)422 int safe_setns(const char *file, const int lineno, int fd, int nstype)
423 {
424 	int ret;
425 
426 	ret = setns(fd, nstype);
427 
428 	if (ret == -1) {
429 		tst_brk_(file, lineno, TBROK | TERRNO, "setns(%i, %i) failed",
430 			fd, nstype);
431 	} else if (ret) {
432 		tst_brk_(file, lineno, TBROK | TERRNO,
433 			"Invalid setns(%i, %i) return value %d", fd, nstype,
434 			ret);
435 	}
436 
437 	return ret;
438 }
439 
tst_safe_ptrace(const char * file,const int lineno,int req,pid_t pid,void * addr,void * data)440 long tst_safe_ptrace(const char *file, const int lineno, int req, pid_t pid,
441 	void *addr, void *data)
442 {
443 	long ret;
444 
445 	errno = 0;
446 	ret = ptrace(req, pid, addr, data);
447 
448 	if (ret == -1) {
449 		tst_brk_(file, lineno, TBROK | TERRNO, "ptrace() failed");
450 	} else if (ret) {
451 		tst_brk_(file, lineno, TBROK | TERRNO,
452 			"Invalid ptrace() return value %ld", ret);
453 	}
454 
455 	return ret;
456 }
457 
safe_pipe2(const char * file,const int lineno,int fildes[2],int flags)458 int safe_pipe2(const char *file, const int lineno, int fildes[2], int flags)
459 {
460 	int ret;
461 
462 	ret = pipe2(fildes, flags);
463 
464 	if (ret == -1) {
465 		tst_brk_(file, lineno, TBROK | TERRNO,
466 			"pipe2({%d,%d}) failed with flag(%d)", fildes[0],
467 			fildes[1], flags);
468 	} else if (ret) {
469 		tst_brk_(file, lineno, TBROK | TERRNO,
470 			"Invalid pipe2({%d,%d}, %d) return value %d",
471 			fildes[0], fildes[1], flags, ret);
472 	}
473 
474 	return ret;
475 }
476 
safe_dup(const char * file,const int lineno,int oldfd)477 int safe_dup(const char *file, const int lineno, int oldfd)
478 {
479 	int rval;
480 
481 	rval = dup(oldfd);
482 
483 	if (rval == -1) {
484 		tst_brk_(file, lineno, TBROK | TERRNO,
485 			"dup(%i) failed", oldfd);
486 	} else if (rval < 0) {
487 		tst_brk_(file, lineno, TBROK | TERRNO,
488 			"Invalid dup(%i) return value %d", oldfd, rval);
489 	}
490 
491 	return rval;
492 }
493 
safe_dup2(const char * file,const int lineno,int oldfd,int newfd)494 int safe_dup2(const char *file, const int lineno, int oldfd, int newfd)
495 {
496 	int rval;
497 
498 	rval = dup2(oldfd, newfd);
499 
500 	if (rval == -1) {
501 		tst_brk_(file, lineno, TBROK | TERRNO,
502 			 "dup2(%i, %i) failed", oldfd, newfd);
503 	} else if (rval != newfd) {
504 		tst_brk_(file, lineno, TBROK | TERRNO,
505 			 "Invalid dup2(%i, %i) return value %d",
506 			 oldfd, newfd, rval);
507 	}
508 
509 	return rval;
510 }
511 
safe_realloc(const char * file,const int lineno,void * ptr,size_t size)512 void *safe_realloc(const char *file, const int lineno, void *ptr, size_t size)
513 {
514 	void *ret;
515 
516 	ret = realloc(ptr, size);
517 
518 	if (!ret) {
519 		tst_brk_(file, lineno, TBROK | TERRNO,
520 			"realloc(%p, %zu) failed", ptr, size);
521 	}
522 
523 	return ret;
524 }
525 
safe_signal(const char * file,const int lineno,int signum,sighandler_t handler)526 sighandler_t safe_signal(const char *file, const int lineno,
527 	int signum, sighandler_t handler)
528 {
529 	sighandler_t rval;
530 
531 	rval = signal(signum, handler);
532 
533 	if (rval == SIG_ERR) {
534 		tst_brk_(file, lineno, TBROK | TERRNO,
535 			"signal(%d,%p) failed",
536 			signum, handler);
537 	}
538 
539 	return rval;
540 }
541 
safe_cmd(const char * file,const int lineno,const char * const argv[],const char * stdout_path,const char * stderr_path)542 void safe_cmd(const char *file, const int lineno, const char *const argv[],
543 	const char *stdout_path, const char *stderr_path)
544 {
545 	int rval;
546 
547 	switch ((rval = tst_cmd(argv, stdout_path, stderr_path,
548 		TST_CMD_PASS_RETVAL | TST_CMD_TCONF_ON_MISSING))) {
549 	case 0:
550 		break;
551 	default:
552 		tst_brk_(file, lineno, TBROK, "%s failed (%d)", argv[0], rval);
553 	}
554 }
555