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