void safe_unshare(const char *file, const int lineno, int flags) { int res; res = unshare(flags); if (res == -1) { if (errno == EINVAL) { tst_brk_(file, lineno, TCONF | TERRNO, "unshare(%d) unsupported", flags); } else { tst_brk_(file, lineno, TBROK | TERRNO, "unshare(%d) failed", flags); } } }
void check_mfd_non_writeable(const char *filename, const int lineno, int fd) { void *p; /* verify write() fails */ TEST(write(fd, "data", 4)); if (TEST_RETURN < 0) { if (TEST_ERRNO != EPERM) { tst_brk_(filename, lineno, TFAIL | TTERRNO, "write() didn't fail as expected"); } } else { tst_brk_(filename, lineno, TFAIL, "write() succeeded unexpectedly"); } tst_res_(filename, lineno, TPASS | TTERRNO, "write failed as expected"); /* verify PROT_READ | PROT_WRITE is not allowed */ check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); /* verify PROT_WRITE is not allowed */ check_mmap_fail(filename, lineno, NULL, MFD_DEF_SIZE, PROT_WRITE, MAP_SHARED, fd, 0); /* Verify PROT_READ with MAP_SHARED with a following mprotect is not * allowed. Note that for r/w the kernel already prevents the mmap. */ p = mmap(NULL, MFD_DEF_SIZE, PROT_READ, MAP_SHARED, fd, 0); if (p != MAP_FAILED) { if (mprotect(p, MFD_DEF_SIZE, PROT_READ | PROT_WRITE) >= 0) { tst_brk_(filename, lineno, TFAIL | TERRNO, "mmap()+mprotect() succeeded unexpectedly"); } } /* verify PUNCH_HOLE fails */ check_fallocate_fail(filename, lineno, fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, MFD_DEF_SIZE); }
void check_mprotect(const char *file, const int lineno, void *addr, size_t length, int prot) { if (mprotect(addr, length, prot) < 0) { tst_brk_(file, lineno, TFAIL | TERRNO, "mprotect(%p, %zu, %d) failed", addr, length, prot); } tst_res_(file, lineno, TPASS, "mprotect(%p, %zu, %d) succeeded", addr, length, prot); }
void check_mfd_fail_add_seals(const char *filename, const int lineno, int fd, int seals) { if (fcntl(fd, F_ADD_SEALS, seals) >= 0) { tst_brk_(filename, lineno, TFAIL, "fcntl(%d, F_ADD_SEALS) succeeded unexpectedly", fd); } tst_res_(filename, lineno, TPASS | TERRNO, "fcntl(%d, F_ADD_SEALS, %d) failed as expected", (fd), (seals)); }
void check_mfd_has_seals(const char *file, const int lineno, int fd, int seals) { int ret = SAFE_FCNTL((fd), F_GET_SEALS); if (ret != seals) { tst_brk_(file, lineno, TFAIL, "fd %d doesn't have expected seals (%d expected %d)", fd, ret, seals); } tst_res_(file, lineno, TPASS, "fd %d has expected seals (%d)", fd, seals); }
int safe_chroot(const char *file, const int lineno, const char *path) { int rval; rval = chroot(path); if (rval == -1) { tst_brk_(file, lineno, TBROK | TERRNO, "chroot(%s) failed", path); } return rval; }
int safe_personality(const char *filename, unsigned int lineno, unsigned long persona) { int prev_persona = personality(persona); if (prev_persona < 0) { tst_brk_(filename, lineno, TBROK | TERRNO, "persona(%ld) failed", persona); } return prev_persona; }
void tst_brkm_(const char *file, const int lineno, int ttype, void (*func)(void), const char *arg_fmt, ...) { char tmesg[USERMESG]; EXPAND_VAR_ARGS(tmesg, arg_fmt, USERMESG); if (tst_test) { if (func) { tst_brk_(file, lineno, TBROK, "Non-NULL cleanup in newlib!"); } tst_brk_(file, lineno, ttype, "%s", tmesg); } else { tst_brk__(file, lineno, ttype, func, "%s", tmesg); } /* Shouldn't be reached, but fixes build time warnings about noreturn. */ abort(); }
struct group *safe_getgrgid(const char *file, const int lineno, gid_t gid) { struct group *rval; errno = 0; rval = getgrgid(gid); if (rval == NULL) { tst_brk_(file, lineno, TBROK | TERRNO, "getgrgid(%li) failed", (long)gid); } return rval; }
int safe_setregid(const char *file, const int lineno, gid_t rgid, gid_t egid) { int rval; rval = setregid(rgid, egid); if (rval == -1) { tst_brk_(file, lineno, TBROK | TERRNO, "setregid(%li, %li) failed", (long)rgid, (long)egid); } return rval; }
struct group *safe_getgrnam(const char *file, const int lineno, const char *name) { struct group *rval; errno = 0; rval = getgrnam(name); if (rval == NULL) { tst_brk_(file, lineno, TBROK | TERRNO, "getgrnam(%s) failed", name); } return rval; }
pid_t safe_fork(const char *filename, unsigned int lineno) { pid_t pid; if (!tst_test->forks_child) tst_brk(TBROK, "test.forks_child must be set!"); fflush(stdout); pid = fork(); if (pid < 0) tst_brk_(filename, lineno, TBROK | TERRNO, "fork() failed"); return pid; }
int safe_pthread_join(const char *file, const int lineno, pthread_t thread_id, void **retval) { int rval; rval = pthread_join(thread_id, retval); if (rval) { tst_brk_(file, lineno, TBROK, "pthread_join(..., %p) failed: %s", retval, tst_strerrno(rval)); } return rval; }
void check_mfd_size(const char *filename, const int lineno, int fd, size_t size) { struct stat st; safe_fstat(filename, lineno, fd, &st); if (st.st_size != (long)size) { tst_brk_(filename, lineno, TFAIL, "fstat(%d, &st): unexpected file size", fd); } tst_res_(filename, lineno, TPASS, "fstat(%d, &st): file size is correct", fd); }
void check_mfd_fail_new(const char *filename, const int lineno, const char *name, int flags) { int fd; fd = sys_memfd_create(name, flags); if (fd >= 0) { safe_close(filename, lineno, NULL, fd); tst_brk_(filename, lineno, TFAIL, "memfd_create(%s, %d) succeeded unexpectedly", name, flags); } tst_res_(filename, lineno, TPASS | TERRNO, "memfd_create(%s, %d) failed as expected", name, flags); }
int safe_sigaction(const char *file, const int lineno, int signum, const struct sigaction *act, struct sigaction *oldact) { int rval; rval = sigaction(signum, act, oldact); if (rval == -1) { tst_brk_(file, lineno, TBROK | TERRNO, "sigaction(%s (%d), %p, %p) failed", tst_strsig(signum), signum, act, oldact); } return rval; }
int safe_pthread_create(const char *file, const int lineno, pthread_t *thread_id, const pthread_attr_t *attr, void *(*thread_fn)(void *), void *arg) { int rval; rval = pthread_create(thread_id, attr, thread_fn, arg); if (rval) { tst_brk_(file, lineno, TBROK, "pthread_create(%p,%p,%p,%p) failed: %s", thread_id, attr, thread_fn, arg, tst_strerrno(rval)); } return rval; }
int mfd_flags_available(const char *filename, const int lineno, unsigned int flags) { TEST(sys_memfd_create("dummy_call", flags)); if (TEST_RETURN < 0) { if (TEST_ERRNO != EINVAL) { tst_brk_(filename, lineno, TBROK | TTERRNO, "memfd_create() failed"); } return 0; } SAFE_CLOSE(TEST_RETURN); return 1; }
int check_mfd_new(const char *filename, const int lineno, const char *name, loff_t sz, int flags) { int fd; fd = sys_memfd_create(name, flags); if (fd < 0) { tst_brk_(filename, lineno, TBROK | TERRNO, "memfd_create(%s, %d) failed", name, flags); } tst_res_(filename, lineno, TPASS, "memfd_create(%s, %d) succeeded", name, flags); check_ftruncate(filename, lineno, fd, sz); return fd; }
int check_fallocate(const char *filename, const int lineno, int fd, int mode, off_t offset, off_t len) { int r; r = fallocate(fd, mode, offset, len); if (r < 0) { tst_brk_(filename, lineno, TFAIL | TERRNO, "fallocate(%d, %d, %ld, %ld) failed", fd, mode, offset, len); } tst_res_(filename, lineno, TPASS, "fallocate(%d, %d, %ld, %ld) succeeded", fd, mode, offset, len); return r; }
int get_mfd_all_available_flags(const char *filename, const int lineno) { unsigned int i; int flag; int flags2test[] = FLAGS_ALL_ARRAY_INITIALIZER; int flags_available = 0; if (!MFD_FLAGS_AVAILABLE(0)) { tst_brk_(filename, lineno, TCONF, "memfd_create(0) not implemented"); } for (i = 0; i < ARRAY_SIZE(flags2test); i++) { flag = flags2test[i]; if (MFD_FLAGS_AVAILABLE(flag)) flags_available |= flag; } return flags_available; }