1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) Linux Test Project, 2010-2020
4 */
5
6 #define _GNU_SOURCE
7 #include <sys/types.h>
8 #include <sys/mman.h>
9 #include <sys/resource.h>
10 #include <sys/stat.h>
11 #include <sys/wait.h>
12 #include <sys/mount.h>
13 #include <sys/xattr.h>
14 #include <sys/sysinfo.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <libgen.h>
18 #include <limits.h>
19 #include <pwd.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <malloc.h>
24 #include "test.h"
25 #include "safe_macros.h"
26
safe_basename(const char * file,const int lineno,void (* cleanup_fn)(void),char * path)27 char *safe_basename(const char *file, const int lineno,
28 void (*cleanup_fn) (void), char *path)
29 {
30 char *rval;
31
32 rval = basename(path);
33
34 if (rval == NULL) {
35 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
36 "basename(%s) failed", path);
37 }
38
39 return rval;
40 }
41
42 int
safe_chdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * path)43 safe_chdir(const char *file, const int lineno, void (*cleanup_fn) (void),
44 const char *path)
45 {
46 int rval;
47
48 rval = chdir(path);
49
50 if (rval == -1) {
51 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
52 "chdir(%s) failed", path);
53 } else if (rval) {
54 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
55 "Invalid chdir(%s) return value %d", path, rval);
56 }
57
58 return rval;
59 }
60
61 int
safe_close(const char * file,const int lineno,void (* cleanup_fn)(void),int fildes)62 safe_close(const char *file, const int lineno, void (*cleanup_fn) (void),
63 int fildes)
64 {
65 int rval;
66
67 rval = close(fildes);
68
69 if (rval == -1) {
70 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
71 "close(%d) failed", fildes);
72 } else if (rval) {
73 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
74 "Invalid close(%d) return value %d", fildes, rval);
75 }
76
77 return rval;
78 }
79
80 int
safe_creat(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)81 safe_creat(const char *file, const int lineno, void (*cleanup_fn) (void),
82 const char *pathname, mode_t mode)
83 {
84 int rval;
85
86 rval = creat(pathname, mode);
87
88 if (rval == -1) {
89 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
90 "creat(%s,%04o) failed", pathname, mode);
91 } else if (rval < 0) {
92 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
93 "Invalid creat(%s,%04o) return value %d", pathname,
94 mode, rval);
95 }
96
97 return rval;
98 }
99
safe_dirname(const char * file,const int lineno,void (* cleanup_fn)(void),char * path)100 char *safe_dirname(const char *file, const int lineno,
101 void (*cleanup_fn) (void), char *path)
102 {
103 char *rval;
104
105 rval = dirname(path);
106
107 if (rval == NULL) {
108 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
109 "dirname(%s) failed", path);
110 }
111
112 return rval;
113 }
114
safe_getcwd(const char * file,const int lineno,void (* cleanup_fn)(void),char * buf,size_t size)115 char *safe_getcwd(const char *file, const int lineno, void (*cleanup_fn) (void),
116 char *buf, size_t size)
117 {
118 char *rval;
119
120 rval = getcwd(buf, size);
121
122 if (rval == NULL) {
123 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
124 "getcwd(%p,%zu) failed", buf, size);
125 }
126
127 return rval;
128 }
129
safe_getpwnam(const char * file,const int lineno,void (* cleanup_fn)(void),const char * name)130 struct passwd *safe_getpwnam(const char *file, const int lineno,
131 void (*cleanup_fn) (void), const char *name)
132 {
133 struct passwd *rval;
134
135 rval = getpwnam(name);
136
137 if (rval == NULL) {
138 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
139 "getpwnam(%s) failed", name);
140 }
141
142 return rval;
143 }
144
145 int
safe_getrusage(const char * file,const int lineno,void (* cleanup_fn)(void),int who,struct rusage * usage)146 safe_getrusage(const char *file, const int lineno, void (*cleanup_fn) (void),
147 int who, struct rusage *usage)
148 {
149 int rval;
150
151 rval = getrusage(who, usage);
152
153 if (rval == -1) {
154 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
155 "getrusage(%d,%p) failed", who, usage);
156 } else if (rval) {
157 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
158 "Invalid getrusage(%d,%p) return value %d", who,
159 usage, rval);
160 }
161
162 return rval;
163 }
164
safe_malloc(const char * file,const int lineno,void (* cleanup_fn)(void),size_t size)165 void *safe_malloc(const char *file, const int lineno, void (*cleanup_fn) (void),
166 size_t size)
167 {
168 void *rval;
169
170 rval = malloc(size);
171
172 if (rval == NULL) {
173 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
174 "malloc(%zu) failed", size);
175 }
176
177 return rval;
178 }
179
safe_mkdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)180 int safe_mkdir(const char *file, const int lineno, void (*cleanup_fn) (void),
181 const char *pathname, mode_t mode)
182 {
183 int rval;
184
185 rval = mkdir(pathname, mode);
186
187 if (rval == -1) {
188 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
189 "mkdir(%s, %04o) failed", pathname, mode);
190 } else if (rval) {
191 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
192 "Invalid mkdir(%s, %04o) return value %d", pathname,
193 mode, rval);
194 }
195
196 return (rval);
197 }
198
safe_rmdir(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname)199 int safe_rmdir(const char *file, const int lineno, void (*cleanup_fn) (void),
200 const char *pathname)
201 {
202 int rval;
203
204 rval = rmdir(pathname);
205
206 if (rval == -1) {
207 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
208 "rmdir(%s) failed", pathname);
209 } else if (rval) {
210 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
211 "Invalid rmdir(%s) return value %d", pathname, rval);
212 }
213
214 return (rval);
215 }
216
safe_munmap(const char * file,const int lineno,void (* cleanup_fn)(void),void * addr,size_t length)217 int safe_munmap(const char *file, const int lineno, void (*cleanup_fn) (void),
218 void *addr, size_t length)
219 {
220 int rval;
221
222 rval = munmap(addr, length);
223
224 if (rval == -1) {
225 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
226 "munmap(%p,%zu) failed", addr, length);
227 } else if (rval) {
228 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
229 "Invalid munmap(%p,%zu) return value %d", addr,
230 length, rval);
231 }
232
233 return rval;
234 }
235
safe_open(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,int oflags,...)236 int safe_open(const char *file, const int lineno, void (*cleanup_fn) (void),
237 const char *pathname, int oflags, ...)
238 {
239 va_list ap;
240 int rval;
241 mode_t mode;
242
243 va_start(ap, oflags);
244
245 /* Android's NDK's mode_t is smaller than an int, which results in
246 * SIGILL here when passing the mode_t type.
247 */
248 mode = va_arg(ap, int);
249
250 va_end(ap);
251
252 rval = open(pathname, oflags, mode);
253
254 if (rval == -1) {
255 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
256 "open(%s,%d,%04o) failed", pathname, oflags, mode);
257 } else if (rval < 0) {
258 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
259 "Invalid open(%s,%d,%04o) return value %d", pathname,
260 oflags, mode, rval);
261 }
262
263 return rval;
264 }
265
safe_pipe(const char * file,const int lineno,void (* cleanup_fn)(void),int fildes[2])266 int safe_pipe(const char *file, const int lineno, void (*cleanup_fn) (void),
267 int fildes[2])
268 {
269 int rval;
270
271 rval = pipe(fildes);
272
273 if (rval == -1) {
274 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
275 "pipe({%d,%d}) failed", fildes[0], fildes[1]);
276 } else if (rval) {
277 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
278 "Invalid pipe({%d,%d}) return value %d", fildes[0],
279 fildes[1], rval);
280 }
281
282 return rval;
283 }
284
safe_read(const char * file,const int lineno,void (* cleanup_fn)(void),char len_strict,int fildes,void * buf,size_t nbyte)285 ssize_t safe_read(const char *file, const int lineno, void (*cleanup_fn) (void),
286 char len_strict, int fildes, void *buf, size_t nbyte)
287 {
288 ssize_t rval;
289
290 rval = read(fildes, buf, nbyte);
291
292 if (rval == -1 || (len_strict && (size_t)rval != nbyte)) {
293 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
294 "read(%d,%p,%zu) failed, returned %zd", fildes, buf,
295 nbyte, rval);
296 } else if (rval < 0) {
297 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
298 "Invalid read(%d,%p,%zu) return value %zd", fildes,
299 buf, nbyte, rval);
300 }
301
302 return rval;
303 }
304
safe_setegid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t egid)305 int safe_setegid(const char *file, const int lineno, void (*cleanup_fn) (void),
306 gid_t egid)
307 {
308 int rval;
309
310 rval = setegid(egid);
311
312 if (rval == -1) {
313 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
314 "setegid(%u) failed", (unsigned int)egid);
315 } else if (rval) {
316 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
317 "Invalid setegid(%u) return value %d",
318 (unsigned int)egid, rval);
319 }
320
321 return rval;
322 }
323
safe_seteuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t euid)324 int safe_seteuid(const char *file, const int lineno, void (*cleanup_fn) (void),
325 uid_t euid)
326 {
327 int rval;
328
329 rval = seteuid(euid);
330
331 if (rval == -1) {
332 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
333 "seteuid(%u) failed", (unsigned int)euid);
334 } else if (rval) {
335 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
336 "Invalid seteuid(%u) return value %d",
337 (unsigned int)euid, rval);
338 }
339
340 return rval;
341 }
342
safe_setgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t gid)343 int safe_setgid(const char *file, const int lineno, void (*cleanup_fn) (void),
344 gid_t gid)
345 {
346 int rval;
347
348 rval = setgid(gid);
349
350 if (rval == -1) {
351 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
352 "setgid(%u) failed", (unsigned int)gid);
353 } else if (rval) {
354 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
355 "Invalid setgid(%u) return value %d",
356 (unsigned int)gid, rval);
357 }
358
359 return rval;
360 }
361
safe_setuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t uid)362 int safe_setuid(const char *file, const int lineno, void (*cleanup_fn) (void),
363 uid_t uid)
364 {
365 int rval;
366
367 rval = setuid(uid);
368
369 if (rval == -1) {
370 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
371 "setuid(%u) failed", (unsigned int)uid);
372 } else if (rval) {
373 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
374 "Invalid setuid(%u) return value %d",
375 (unsigned int)uid, rval);
376 }
377
378 return rval;
379 }
380
safe_getresuid(const char * file,const int lineno,void (* cleanup_fn)(void),uid_t * ruid,uid_t * euid,uid_t * suid)381 int safe_getresuid(const char *file, const int lineno, void (*cleanup_fn)(void),
382 uid_t *ruid, uid_t *euid, uid_t *suid)
383 {
384 int rval;
385
386 rval = getresuid(ruid, euid, suid);
387
388 if (rval == -1) {
389 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
390 "getresuid(%p, %p, %p) failed", ruid, euid, suid);
391 } else if (rval) {
392 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
393 "Invalid getresuid(%p, %p, %p) return value %d", ruid,
394 euid, suid, rval);
395 }
396
397 return rval;
398 }
399
safe_getresgid(const char * file,const int lineno,void (* cleanup_fn)(void),gid_t * rgid,gid_t * egid,gid_t * sgid)400 int safe_getresgid(const char *file, const int lineno, void (*cleanup_fn)(void),
401 gid_t *rgid, gid_t *egid, gid_t *sgid)
402 {
403 int rval;
404
405 rval = getresgid(rgid, egid, sgid);
406
407 if (rval == -1) {
408 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
409 "getresgid(%p, %p, %p) failed", rgid, egid, sgid);
410 } else if (rval) {
411 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
412 "Invalid getresgid(%p, %p, %p) return value %d", rgid,
413 egid, sgid, rval);
414 }
415
416 return rval;
417 }
418
safe_unlink(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname)419 int safe_unlink(const char *file, const int lineno, void (*cleanup_fn) (void),
420 const char *pathname)
421 {
422 int rval;
423
424 rval = unlink(pathname);
425
426 if (rval == -1) {
427 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
428 "unlink(%s) failed", pathname);
429 } else if (rval) {
430 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
431 "Invalid unlink(%s) return value %d", pathname, rval);
432 }
433
434 return rval;
435 }
436
437
safe_link(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)438 int safe_link(const char *file, const int lineno,
439 void (cleanup_fn)(void), const char *oldpath,
440 const char *newpath)
441 {
442 int rval;
443
444 rval = link(oldpath, newpath);
445
446 if (rval == -1) {
447 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
448 "link(%s,%s) failed", oldpath, newpath);
449 } else if (rval) {
450 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
451 "Invalid link(%s,%s) return value %d", oldpath,
452 newpath, rval);
453 }
454
455 return rval;
456 }
457
safe_linkat(const char * file,const int lineno,void (cleanup_fn)(void),int olddirfd,const char * oldpath,int newdirfd,const char * newpath,int flags)458 int safe_linkat(const char *file, const int lineno,
459 void (cleanup_fn)(void), int olddirfd, const char *oldpath,
460 int newdirfd, const char *newpath, int flags)
461 {
462 int rval;
463
464 rval = linkat(olddirfd, oldpath, newdirfd, newpath, flags);
465
466 if (rval == -1) {
467 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
468 "linkat(%d,%s,%d,%s,%d) failed", olddirfd, oldpath,
469 newdirfd, newpath, flags);
470 } else if (rval) {
471 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
472 "Invalid linkat(%d,%s,%d,%s,%d) return value %d",
473 olddirfd, oldpath, newdirfd, newpath, flags, rval);
474 }
475
476 return rval;
477 }
478
safe_readlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,char * buf,size_t bufsize)479 ssize_t safe_readlink(const char *file, const int lineno,
480 void (cleanup_fn)(void), const char *path,
481 char *buf, size_t bufsize)
482 {
483 ssize_t rval;
484
485 rval = readlink(path, buf, bufsize);
486
487 if (rval == -1) {
488 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
489 "readlink(%s,%p,%zu) failed", path, buf, bufsize);
490 } else if (rval < 0) {
491 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
492 "Invalid readlink(%s,%p,%zu) return value %zd", path,
493 buf, bufsize, rval);
494 } else {
495 /* readlink does not append a NUL byte to the buffer.
496 * Add it now. */
497 if ((size_t) rval < bufsize)
498 buf[rval] = '\0';
499 else
500 buf[bufsize-1] = '\0';
501 }
502
503 return rval;
504 }
505
safe_symlink(const char * file,const int lineno,void (cleanup_fn)(void),const char * oldpath,const char * newpath)506 int safe_symlink(const char *file, const int lineno,
507 void (cleanup_fn)(void), const char *oldpath,
508 const char *newpath)
509 {
510 int rval;
511
512 rval = symlink(oldpath, newpath);
513
514 if (rval == -1) {
515 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
516 "symlink(%s,%s) failed", oldpath, newpath);
517 } else if (rval) {
518 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
519 "Invalid symlink(%s,%s) return value %d", oldpath,
520 newpath, rval);
521 }
522
523 return rval;
524 }
525
safe_write(const char * file,const int lineno,void (cleanup_fn)(void),char len_strict,int fildes,const void * buf,size_t nbyte)526 ssize_t safe_write(const char *file, const int lineno, void (cleanup_fn) (void),
527 char len_strict, int fildes, const void *buf, size_t nbyte)
528 {
529 ssize_t rval;
530
531 rval = write(fildes, buf, nbyte);
532
533 if (rval == -1 || (len_strict && (size_t)rval != nbyte)) {
534 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
535 "write(%d,%p,%zu) failed", fildes, buf, nbyte);
536 } else if (rval < 0) {
537 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
538 "Invalid write(%d,%p,%zu) return value %zd", fildes,
539 buf, nbyte, rval);
540 }
541
542 return rval;
543 }
544
safe_strtol(const char * file,const int lineno,void (cleanup_fn)(void),char * str,long min,long max)545 long safe_strtol(const char *file, const int lineno,
546 void (cleanup_fn) (void), char *str, long min, long max)
547 {
548 long rval;
549 char *endptr;
550
551 errno = 0;
552 rval = strtol(str, &endptr, 10);
553
554 if ((errno == ERANGE && (rval == LONG_MAX || rval == LONG_MIN))
555 || (errno != 0 && rval == 0)) {
556 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
557 "strtol(%s) failed", str);
558 return rval;
559 }
560
561 if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
562 tst_brkm_(file, lineno, TBROK, cleanup_fn,
563 "strtol(%s): Invalid value", str);
564 return 0;
565 }
566
567 if (rval > max || rval < min) {
568 tst_brkm_(file, lineno, TBROK, cleanup_fn,
569 "strtol(%s): %ld is out of range %ld - %ld",
570 str, rval, min, max);
571 return 0;
572 }
573
574 return rval;
575 }
576
safe_strtoul(const char * file,const int lineno,void (cleanup_fn)(void),char * str,unsigned long min,unsigned long max)577 unsigned long safe_strtoul(const char *file, const int lineno,
578 void (cleanup_fn) (void), char *str,
579 unsigned long min, unsigned long max)
580 {
581 unsigned long rval;
582 char *endptr;
583
584 errno = 0;
585 rval = strtoul(str, &endptr, 10);
586
587 if ((errno == ERANGE && rval == ULONG_MAX)
588 || (errno != 0 && rval == 0)) {
589 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
590 "strtoul(%s) failed", str);
591 return rval;
592 }
593
594 if (rval > max || rval < min) {
595 tst_brkm_(file, lineno, TBROK, cleanup_fn,
596 "strtoul(%s): %lu is out of range %lu - %lu",
597 str, rval, min, max);
598 return 0;
599 }
600
601 if (endptr == str || (*endptr != '\0' && *endptr != '\n')) {
602 tst_brkm_(file, lineno, TBROK, cleanup_fn,
603 "Invalid value: '%s'", str);
604 return 0;
605 }
606
607 return rval;
608 }
609
safe_sysconf(const char * file,const int lineno,void (cleanup_fn)(void),int name)610 long safe_sysconf(const char *file, const int lineno,
611 void (cleanup_fn) (void), int name)
612 {
613 long rval;
614
615 errno = 0;
616 rval = sysconf(name);
617
618 if (rval == -1) {
619 if (errno) {
620 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
621 "sysconf(%d) failed", name);
622 } else {
623 tst_resm_(file, lineno, TINFO,
624 "sysconf(%d): queried option is not available or there is no definite limit",
625 name);
626 }
627 }
628
629 return rval;
630 }
631
safe_chmod(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,mode_t mode)632 int safe_chmod(const char *file, const int lineno,
633 void (cleanup_fn)(void), const char *path, mode_t mode)
634 {
635 int rval;
636
637 rval = chmod(path, mode);
638
639 if (rval == -1) {
640 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
641 "chmod(%s,%04o) failed", path, mode);
642 } else if (rval) {
643 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
644 "Invalid chmod(%s,%04o) return value %d", path, mode,
645 rval);
646 }
647
648 return rval;
649 }
650
safe_fchmod(const char * file,const int lineno,void (cleanup_fn)(void),int fd,mode_t mode)651 int safe_fchmod(const char *file, const int lineno,
652 void (cleanup_fn)(void), int fd, mode_t mode)
653 {
654 int rval;
655
656 rval = fchmod(fd, mode);
657
658 if (rval == -1) {
659 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
660 "fchmod(%d,%04o) failed", fd, mode);
661 } else if (rval) {
662 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
663 "Invalid fchmod(%d,%04o) return value %d", fd, mode,
664 rval);
665 }
666
667 return rval;
668 }
669
safe_chown(const char * file,const int lineno,void (cleanup_fn)(void),const char * path,uid_t owner,gid_t group)670 int safe_chown(const char *file, const int lineno, void (cleanup_fn)(void),
671 const char *path, uid_t owner, gid_t group)
672 {
673 int rval;
674
675 rval = chown(path, owner, group);
676
677 if (rval == -1) {
678 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
679 "chown(%s,%d,%d) failed", path, owner, group);
680 } else if (rval) {
681 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
682 "Invalid chown(%s,%d,%d) return value %d", path,
683 owner, group, rval);
684 }
685
686 return rval;
687 }
688
safe_fchown(const char * file,const int lineno,void (cleanup_fn)(void),int fd,uid_t owner,gid_t group)689 int safe_fchown(const char *file, const int lineno, void (cleanup_fn)(void),
690 int fd, uid_t owner, gid_t group)
691 {
692 int rval;
693
694 rval = fchown(fd, owner, group);
695
696 if (rval == -1) {
697 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
698 "fchown(%d,%d,%d) failed", fd, owner, group);
699 } else if (rval) {
700 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
701 "Invalid fchown(%d,%d,%d) return value %d", fd,
702 owner, group, rval);
703 }
704
705 return rval;
706 }
707
safe_wait(const char * file,const int lineno,void (cleanup_fn)(void),int * status)708 pid_t safe_wait(const char *file, const int lineno, void (cleanup_fn)(void),
709 int *status)
710 {
711 pid_t rval;
712
713 rval = wait(status);
714
715 if (rval == -1) {
716 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
717 "wait(%p) failed", status);
718 } else if (rval < 0) {
719 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
720 "Invalid wait(%p) return value %d", status, rval);
721 }
722
723 return rval;
724 }
725
safe_waitpid(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int * status,int opts)726 pid_t safe_waitpid(const char *file, const int lineno, void (cleanup_fn)(void),
727 pid_t pid, int *status, int opts)
728 {
729 pid_t rval;
730
731 rval = waitpid(pid, status, opts);
732
733 if (rval == -1) {
734 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
735 "waitpid(%d,%p,%d) failed", pid, status, opts);
736 } else if (rval < 0) {
737 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
738 "Invalid waitpid(%d,%p,%d) return value %d", pid,
739 status, opts, rval);
740 }
741
742 return rval;
743 }
744
safe_memalign(const char * file,const int lineno,void (* cleanup_fn)(void),size_t alignment,size_t size)745 void *safe_memalign(const char *file, const int lineno,
746 void (*cleanup_fn) (void), size_t alignment, size_t size)
747 {
748 void *rval;
749
750 rval = memalign(alignment, size);
751
752 if (rval == NULL) {
753 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
754 "memalign() failed");
755 }
756
757 return rval;
758 }
759
safe_kill(const char * file,const int lineno,void (cleanup_fn)(void),pid_t pid,int sig)760 int safe_kill(const char *file, const int lineno, void (cleanup_fn)(void),
761 pid_t pid, int sig)
762 {
763 int rval;
764
765 rval = kill(pid, sig);
766
767 if (rval == -1) {
768 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
769 "kill(%d,%s) failed", pid, tst_strsig(sig));
770 } else if (rval) {
771 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
772 "Invalid kill(%d,%s) return value %d", pid,
773 tst_strsig(sig), rval);
774 }
775
776 return rval;
777 }
778
safe_mkfifo(const char * file,const int lineno,void (* cleanup_fn)(void),const char * pathname,mode_t mode)779 int safe_mkfifo(const char *file, const int lineno,
780 void (*cleanup_fn)(void), const char *pathname, mode_t mode)
781 {
782 int rval;
783
784 rval = mkfifo(pathname, mode);
785
786 if (rval == -1) {
787 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
788 "mkfifo(%s, %04o) failed", pathname, mode);
789 } else if (rval) {
790 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
791 "Invalid mkfifo(%s, %04o) return value %d", pathname,
792 mode, rval);
793 }
794
795 return rval;
796 }
797
safe_rename(const char * file,const int lineno,void (* cleanup_fn)(void),const char * oldpath,const char * newpath)798 int safe_rename(const char *file, const int lineno, void (*cleanup_fn)(void),
799 const char *oldpath, const char *newpath)
800 {
801 int rval;
802
803 rval = rename(oldpath, newpath);
804
805 if (rval == -1) {
806 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
807 "rename(%s, %s) failed", oldpath, newpath);
808 } else if (rval) {
809 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
810 "Invalid rename(%s, %s) return value %d", oldpath,
811 newpath, rval);
812 }
813
814 return rval;
815 }
816
817 static const char *const fuse_fs_types[] = {
818 "exfat",
819 "ntfs",
820 };
821
possibly_fuse(const char * fs_type)822 static int possibly_fuse(const char *fs_type)
823 {
824 unsigned int i;
825
826 if (!fs_type)
827 return 0;
828
829 for (i = 0; i < ARRAY_SIZE(fuse_fs_types); i++) {
830 if (!strcmp(fuse_fs_types[i], fs_type))
831 return 1;
832 }
833
834 return 0;
835 }
836
safe_mount(const char * file,const int lineno,void (* cleanup_fn)(void),const char * source,const char * target,const char * filesystemtype,unsigned long mountflags,const void * data)837 int safe_mount(const char *file, const int lineno, void (*cleanup_fn)(void),
838 const char *source, const char *target,
839 const char *filesystemtype, unsigned long mountflags,
840 const void *data)
841 {
842 int rval = -1;
843
844 /*
845 * Don't try using the kernel's NTFS driver when mounting NTFS, since
846 * the kernel's NTFS driver doesn't have proper write support.
847 */
848 if (!filesystemtype || strcmp(filesystemtype, "ntfs")) {
849 rval = mount(source, target, filesystemtype, mountflags, data);
850 if (!rval)
851 return 0;
852 }
853
854 /*
855 * The FUSE filesystem executes mount.fuse helper, which tries to
856 * execute corresponding binary name which is encoded at the start of
857 * the source string and separated by # from the device name.
858 *
859 * The mount helpers are called mount.$fs_type.
860 */
861 if (possibly_fuse(filesystemtype)) {
862 char buf[1024];
863
864 tst_resm_(file, lineno, TINFO, "Trying FUSE...");
865 snprintf(buf, sizeof(buf), "mount.%s '%s' '%s'",
866 filesystemtype, source, target);
867
868 rval = tst_system(buf);
869 if (WIFEXITED(rval) && WEXITSTATUS(rval) == 0)
870 return 0;
871
872 tst_brkm_(file, lineno, TBROK, cleanup_fn,
873 "mount.%s failed with %i", filesystemtype, rval);
874 return -1;
875 } else if (rval == -1) {
876 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
877 "mount(%s, %s, %s, %lu, %p) failed", source, target,
878 filesystemtype, mountflags, data);
879 } else {
880 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
881 "Invalid mount(%s, %s, %s, %lu, %p) return value %d",
882 source, target, filesystemtype, mountflags, data,
883 rval);
884 }
885
886 return rval;
887 }
888
safe_umount(const char * file,const int lineno,void (* cleanup_fn)(void),const char * target)889 int safe_umount(const char *file, const int lineno, void (*cleanup_fn)(void),
890 const char *target)
891 {
892 int rval;
893
894 rval = tst_umount(target);
895
896 if (rval == -1) {
897 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
898 "umount(%s) failed", target);
899 } else if (rval) {
900 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
901 "Invalid umount(%s) return value %d", target, rval);
902 }
903
904 return rval;
905 }
906
safe_opendir(const char * file,const int lineno,void (cleanup_fn)(void),const char * name)907 DIR* safe_opendir(const char *file, const int lineno, void (cleanup_fn)(void),
908 const char *name)
909 {
910 DIR *rval;
911
912 rval = opendir(name);
913
914 if (!rval) {
915 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
916 "opendir(%s) failed", name);
917 }
918
919 return rval;
920 }
921
safe_closedir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)922 int safe_closedir(const char *file, const int lineno, void (cleanup_fn)(void),
923 DIR *dirp)
924 {
925 int rval;
926
927 rval = closedir(dirp);
928
929 if (rval == -1) {
930 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
931 "closedir(%p) failed", dirp);
932 } else if (rval) {
933 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
934 "Invalid closedir(%p) return value %d", dirp, rval);
935 }
936
937 return rval;
938 }
939
safe_readdir(const char * file,const int lineno,void (cleanup_fn)(void),DIR * dirp)940 struct dirent *safe_readdir(const char *file, const int lineno, void (cleanup_fn)(void),
941 DIR *dirp)
942 {
943 struct dirent *rval;
944 int err = errno;
945
946 errno = 0;
947 rval = readdir(dirp);
948
949 if (!rval && errno) {
950 tst_brkm_(file, lineno, TBROK | TERRNO, cleanup_fn,
951 "readdir(%p) failed", dirp);
952 }
953
954 errno = err;
955 return rval;
956 }
957
safe_getpriority(const char * file,const int lineno,int which,id_t who)958 int safe_getpriority(const char *file, const int lineno, int which, id_t who)
959 {
960 int rval, err = errno;
961
962 errno = 0;
963 rval = getpriority(which, who);
964
965 if (rval == -1 && errno) {
966 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
967 "getpriority(%i, %i) failed", which, who);
968 } else if (errno) {
969 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
970 "getpriority(%i, %i) failed with return value %d",
971 which, who, rval);
972 }
973
974 errno = err;
975 return rval;
976 }
977
safe_getxattr(const char * file,const int lineno,const char * path,const char * name,void * value,size_t size)978 ssize_t safe_getxattr(const char *file, const int lineno, const char *path,
979 const char *name, void *value, size_t size)
980 {
981 ssize_t rval;
982
983 rval = getxattr(path, name, value, size);
984
985 if (rval == -1) {
986 if (errno == ENOTSUP) {
987 tst_brkm_(file, lineno, TCONF, NULL,
988 "no xattr support in fs or mounted without user_xattr option");
989 return rval;
990 }
991
992 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
993 "getxattr(%s, %s, %p, %zu) failed",
994 path, name, value, size);
995 } else if (rval < 0) {
996 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
997 "Invalid getxattr(%s, %s, %p, %zu) return value %zd",
998 path, name, value, size, rval);
999 }
1000
1001 return rval;
1002 }
1003
safe_setxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)1004 int safe_setxattr(const char *file, const int lineno, const char *path,
1005 const char *name, const void *value, size_t size, int flags)
1006 {
1007 int rval;
1008
1009 rval = setxattr(path, name, value, size, flags);
1010
1011 if (rval == -1) {
1012 if (errno == ENOTSUP) {
1013 tst_brkm_(file, lineno, TCONF, NULL,
1014 "no xattr support in fs or mounted without user_xattr option");
1015 return rval;
1016 }
1017
1018 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1019 "setxattr(%s, %s, %p, %zu) failed",
1020 path, name, value, size);
1021 } else if (rval) {
1022 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1023 "Invalid setxattr(%s, %s, %p, %zu) return value %d",
1024 path, name, value, size, rval);
1025 }
1026
1027 return rval;
1028 }
1029
safe_lsetxattr(const char * file,const int lineno,const char * path,const char * name,const void * value,size_t size,int flags)1030 int safe_lsetxattr(const char *file, const int lineno, const char *path,
1031 const char *name, const void *value, size_t size, int flags)
1032 {
1033 int rval;
1034
1035 rval = lsetxattr(path, name, value, size, flags);
1036
1037 if (rval == -1) {
1038 if (errno == ENOTSUP) {
1039 tst_brkm_(file, lineno, TCONF, NULL,
1040 "no xattr support in fs or mounted without user_xattr option");
1041 return rval;
1042 }
1043
1044 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1045 "lsetxattr(%s, %s, %p, %zu, %i) failed",
1046 path, name, value, size, flags);
1047 } else if (rval) {
1048 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1049 "Invalid lsetxattr(%s, %s, %p, %zu, %i) return value %d",
1050 path, name, value, size, flags, rval);
1051 }
1052
1053 return rval;
1054 }
1055
safe_fsetxattr(const char * file,const int lineno,int fd,const char * name,const void * value,size_t size,int flags)1056 int safe_fsetxattr(const char *file, const int lineno, int fd, const char *name,
1057 const void *value, size_t size, int flags)
1058 {
1059 int rval;
1060
1061 rval = fsetxattr(fd, name, value, size, flags);
1062
1063 if (rval == -1) {
1064 if (errno == ENOTSUP) {
1065 tst_brkm_(file, lineno, TCONF, NULL,
1066 "no xattr support in fs or mounted without user_xattr option");
1067 return rval;
1068 }
1069
1070 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1071 "fsetxattr(%i, %s, %p, %zu, %i) failed",
1072 fd, name, value, size, flags);
1073 } else if (rval) {
1074 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1075 "Invalid fsetxattr(%i, %s, %p, %zu, %i) return value %d",
1076 fd, name, value, size, flags, rval);
1077 }
1078
1079 return rval;
1080 }
1081
safe_removexattr(const char * file,const int lineno,const char * path,const char * name)1082 int safe_removexattr(const char *file, const int lineno, const char *path,
1083 const char *name)
1084 {
1085 int rval;
1086
1087 rval = removexattr(path, name);
1088
1089 if (rval == -1) {
1090 if (errno == ENOTSUP) {
1091 tst_brkm_(file, lineno, TCONF, NULL,
1092 "no xattr support in fs or mounted without user_xattr option");
1093 return rval;
1094 }
1095
1096 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1097 "removexattr(%s, %s) failed", path, name);
1098 } else if (rval) {
1099 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1100 "Invalid removexattr(%s, %s) return value %d", path,
1101 name, rval);
1102 }
1103
1104 return rval;
1105 }
1106
safe_lremovexattr(const char * file,const int lineno,const char * path,const char * name)1107 int safe_lremovexattr(const char *file, const int lineno, const char *path,
1108 const char *name)
1109 {
1110 int rval;
1111
1112 rval = lremovexattr(path, name);
1113
1114 if (rval == -1) {
1115 if (errno == ENOTSUP) {
1116 tst_brkm_(file, lineno, TCONF, NULL,
1117 "no xattr support in fs or mounted without user_xattr option");
1118 return rval;
1119 }
1120
1121 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1122 "lremovexattr(%s, %s) failed", path, name);
1123 } else if (rval) {
1124 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1125 "Invalid lremovexattr(%s, %s) return value %d", path,
1126 name, rval);
1127 }
1128
1129 return rval;
1130 }
1131
safe_fremovexattr(const char * file,const int lineno,int fd,const char * name)1132 int safe_fremovexattr(const char *file, const int lineno, int fd,
1133 const char *name)
1134 {
1135 int rval;
1136
1137 rval = fremovexattr(fd, name);
1138
1139 if (rval == -1) {
1140 if (errno == ENOTSUP) {
1141 tst_brkm_(file, lineno, TCONF, NULL,
1142 "no xattr support in fs or mounted without user_xattr option");
1143 return rval;
1144 }
1145
1146 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1147 "fremovexattr(%i, %s) failed", fd, name);
1148 } else if (rval) {
1149 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1150 "Invalid fremovexattr(%i, %s) return value %d", fd,
1151 name, rval);
1152 }
1153
1154 return rval;
1155 }
1156
safe_fsync(const char * file,const int lineno,int fd)1157 int safe_fsync(const char *file, const int lineno, int fd)
1158 {
1159 int rval;
1160
1161 rval = fsync(fd);
1162
1163 if (rval == -1) {
1164 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1165 "fsync(%i) failed", fd);
1166 } else if (rval) {
1167 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1168 "Invalid fsync(%i) return value %d", fd, rval);
1169 }
1170
1171 return rval;
1172 }
1173
safe_setsid(const char * file,const int lineno)1174 pid_t safe_setsid(const char *file, const int lineno)
1175 {
1176 pid_t rval;
1177
1178 rval = setsid();
1179
1180 if (rval == -1) {
1181 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1182 "setsid() failed");
1183 }
1184
1185 return rval;
1186 }
1187
safe_mknod(const char * file,const int lineno,const char * pathname,mode_t mode,dev_t dev)1188 int safe_mknod(const char *file, const int lineno, const char *pathname,
1189 mode_t mode, dev_t dev)
1190 {
1191 int rval;
1192
1193 rval = mknod(pathname, mode, dev);
1194
1195 if (rval == -1) {
1196 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1197 "mknod() failed");
1198 } else if (rval) {
1199 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1200 "Invalid mknod() return value %d", rval);
1201 }
1202
1203 return rval;
1204 }
1205
safe_mlock(const char * file,const int lineno,const void * addr,size_t len)1206 int safe_mlock(const char *file, const int lineno, const void *addr,
1207 size_t len)
1208 {
1209 int rval;
1210
1211 rval = mlock(addr, len);
1212
1213 if (rval == -1) {
1214 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1215 "mlock() failed");
1216 } else if (rval) {
1217 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1218 "Invalid mlock() return value %d", rval);
1219 }
1220
1221 return rval;
1222 }
1223
safe_munlock(const char * file,const int lineno,const void * addr,size_t len)1224 int safe_munlock(const char *file, const int lineno, const void *addr,
1225 size_t len)
1226 {
1227 int rval;
1228
1229 rval = munlock(addr, len);
1230
1231 if (rval == -1) {
1232 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1233 "munlock() failed");
1234 } else if (rval) {
1235 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1236 "Invalid munlock() return value %d", rval);
1237 }
1238
1239 return rval;
1240 }
1241
safe_mincore(const char * file,const int lineno,void * start,size_t length,unsigned char * vec)1242 int safe_mincore(const char *file, const int lineno, void *start,
1243 size_t length, unsigned char *vec)
1244 {
1245 int rval;
1246
1247 rval = mincore(start, length, vec);
1248
1249 if (rval == -1) {
1250 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1251 "mincore() failed");
1252 } else if (rval) {
1253 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1254 "Invalid mincore() return value %d", rval);
1255 }
1256
1257 return rval;
1258 }
1259
safe_sysinfo(const char * file,const int lineno,struct sysinfo * info)1260 int safe_sysinfo(const char *file, const int lineno, struct sysinfo *info)
1261 {
1262 int ret;
1263
1264 errno = 0;
1265 ret = sysinfo(info);
1266
1267 if (ret == -1) {
1268 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1269 "sysinfo() failed");
1270 } else if (ret) {
1271 tst_brkm_(file, lineno, TBROK | TERRNO, NULL,
1272 "Invalid sysinfo() return value %d", ret);
1273 }
1274
1275 return ret;
1276 }
1277