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