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