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