From 983f575b9291d2a98e453b95d23a4eee5ead2561 Mon Sep 17 00:00:00 2001 From: David Rowland Date: Mon, 3 Jun 2024 16:07:48 +0100 Subject: [PATCH] Fixed variadic arguments for open and added unit tests; Added fcntl; --- README.md | 4 +-- src/rtcheck.cpp | 33 +++++++++++++++----- src/rtcheck.h | 27 +++++++++-------- tests/fail_fcntl.cpp | 42 +++++++++++++++++++++++++ tests/fail_open.cpp | 39 ++++++++++++++++++++++++ tests/pass_unit_tests.cpp | 64 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 187 insertions(+), 22 deletions(-) create mode 100644 tests/fail_fcntl.cpp create mode 100644 tests/fail_open.cpp create mode 100644 tests/pass_unit_tests.cpp diff --git a/README.md b/README.md index aee5832..7ccc131 100644 --- a/README.md +++ b/README.md @@ -120,14 +120,14 @@ void set_error_mode (error_mode); - [x] pthread_rwlock_wrlock ✔ - [x] pthread_spin_lock (linux) - Files - - [x] open + - [x] open ✔ - [x] openat - [ ] close - [x] fopen - [ ] fread - [ ] fwrite - [ ] fclose - - [ ] fcntl + - [x] fcntl ✔ - [ ] creat - [ ] puts - [ ] fputs diff --git a/src/rtcheck.cpp b/src/rtcheck.cpp index aa11aab..2c052c7 100644 --- a/src/rtcheck.cpp +++ b/src/rtcheck.cpp @@ -233,7 +233,9 @@ struct check_flags_tests assert(! are_all_bits_enabled (to_underlying (check_flags::malloc) + to_underlying (check_flags::realloc), 0b101)); assert(are_all_bits_enabled (to_underlying (check_flags::malloc) + to_underlying (check_flags::calloc), 0b100)); assert(are_all_bits_enabled (to_underlying (check_flags::syscall) + to_underlying (check_flags::openat), 0b0)); - assert(! are_all_bits_enabled (to_underlying (check_flags::syscall) + to_underlying (check_flags::openat), 0b10010000000000000000000000000000000)); + auto a1 = to_underlying (check_flags::syscall); + auto a2 = to_underlying (check_flags::openat); + assert(! are_all_bits_enabled (to_underlying (check_flags::syscall) + to_underlying (check_flags::openat), 0b10001000000000000000000000000000000000)); } }; @@ -246,6 +248,7 @@ bool is_check_enabled_for_thread (check_flags check) return are_all_bits_enabled (static_cast (check), get_disabled_flags_for_thread()); } + //============================================================================== // details //============================================================================== @@ -536,10 +539,10 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) va_list args; va_start(args, oflag); - auto result = REAL(open)(path, oflag, args); + const mode_t mode = va_arg(args, int); va_end(args); - return result; + return REAL(open)(path, oflag, mode); } INTERCEPTOR(FILE*, fopen, const char *path, const char *mode) @@ -556,15 +559,27 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) { log_function_if_realtime_context_and_enabled (rtc::check_flags::openat, __func__); + INTERCEPT_FUNCTION(int, openat, int, const char*, int, ...); + va_list args; va_start(args, oflag); - INTERCEPT_FUNCTION(int, openat, int, const char*, int, ...); - auto result = REAL(openat)(fd, path, oflag, args); + mode_t mode = va_arg(args, int); va_end(args); - return result; + return REAL(openat)(fd, path, oflag, args); } +INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) +{ + log_function_if_realtime_context_and_enabled (rtc::check_flags::fcntl, __func__); + + va_list args; + va_start(args, cmd); + void *arg = va_arg(args, void*); + va_end(args); + + return fcntl(filedes, cmd, arg); +} //============================================================================== // system @@ -591,13 +606,17 @@ INTERCEPTOR(long, context_switch, struct task_struct *prev, struct task_struct * // syscall is deprecated, but still in use in libc++ #pragma clang diagnostic ignored "-Wdeprecated-declarations" +#define FORWARD_ARGS(func, ...) func(__VA_ARGS__) +#define EXPAND_ARGS(...) (__VA_ARGS__) + INTERCEPTOR(long int, syscall, long int sid, ...) { log_function_if_realtime_context_and_enabled (rtc::check_flags::syscall, __func__); + INTERCEPT_FUNCTION(long, syscall, long, ...); + va_list args; va_start(args, sid); - INTERCEPT_FUNCTION(long, syscall, long, ...); va_end(args); return REAL(syscall)(sid); diff --git a/src/rtcheck.h b/src/rtcheck.h index 918bcc6..2fdd676 100644 --- a/src/rtcheck.h +++ b/src/rtcheck.h @@ -106,8 +106,8 @@ namespace rtc pthread_rwlock_wrlock = 1 << 21, pthread_spin_lock = 1 << 22, // linux only futex = 1 << 23, // linux only - OSSpinLockLock = 1ull << 35, // apple only - os_unfair_lock_lock = 1ull << 36, // apple only + OSSpinLockLock = 1 << 24, // apple only + os_unfair_lock_lock = 1 << 25, // apple only threads = pthread_create | pthread_mutex_lock | pthread_mutex_unlock | pthread_join | pthread_cond_signal | pthread_cond_broadcast | pthread_cond_wait @@ -118,29 +118,30 @@ namespace rtc //============================================================================== // sleeping //============================================================================== - sleep = 1 << 24, - usleep = 1 << 25, - nanosleep = 1 << 26, + sleep = 1 << 26, + usleep = 1 << 27, + nanosleep = 1 << 28, sleeping = sleep | usleep | nanosleep, //============================================================================== // files //============================================================================== - stat = 1 << 27, - fstat = 1 << 28, - open = 1 << 29, - fopen = 1 << 30, - openat = 1ull << 31, + stat = 1 << 29, + fstat = 1 << 30, + open = 1ull << 31, + fopen = 1ull << 32, + openat = 1ull << 33, + fcntl = 1ull << 34, files = stat | fstat | open | fopen | openat, //============================================================================== // system //============================================================================== - schedule = 1ull << 32, // linux only - context_switch = 1ull << 33, // linux only - syscall = 1ull << 34, + schedule = 1ull << 35, // linux only + context_switch = 1ull << 36, // linux only + syscall = 1ull << 37, sys = schedule | context_switch | syscall }; diff --git a/tests/fail_fcntl.cpp b/tests/fail_fcntl.cpp new file mode 100644 index 0000000..22ad3c6 --- /dev/null +++ b/tests/fail_fcntl.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +int main() +{ + rtc::realtime_context rc; + + namespace fs = std::filesystem; + const fs::path temp_file = std::tmpnam (nullptr); + int fd = creat(temp_file.c_str(), S_IRUSR | S_IWUSR); + assert(fd != -1); + + auto func = [fd] { + struct flock lock{}; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = ::getpid(); + + assert(fcntl(fd, F_GETLK, &lock) == 0); + assert(lock.l_type == F_UNLCK); + }; + + close(fd); + std::remove (temp_file.c_str()); + + return 0; +} + +#pragma clang diagnostic pop diff --git a/tests/fail_open.cpp b/tests/fail_open.cpp new file mode 100644 index 0000000..fd0ab60 --- /dev/null +++ b/tests/fail_open.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +int main() +{ + rtc::realtime_context rc; + + namespace fs = std::filesystem; + const fs::path temp_file = std::tmpnam (nullptr); + + const int mode = S_IRGRP | S_IROTH | S_IRUSR | S_IWUSR; + const int fd = open (temp_file.c_str(), O_CREAT | O_WRONLY, mode); + assert(fd != -1); + close(fd); + + struct stat st; + assert(stat(temp_file.c_str(), &st) == 0); + + // Mask st_mode to get permission bits only + assert((st.st_mode & 0777) == mode); + + auto res = fs::remove (temp_file); + assert (res); + + return 0; +} + +#pragma clang diagnostic pop diff --git a/tests/pass_unit_tests.cpp b/tests/pass_unit_tests.cpp new file mode 100644 index 0000000..483b337 --- /dev/null +++ b/tests/pass_unit_tests.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +bool test_openCreatesFileWithProperMode() +{ + namespace fs = std::filesystem; + const fs::path temp_file = std::tmpnam (nullptr); + + const int mode = S_IRGRP | S_IROTH | S_IRUSR | S_IWUSR; + const int fd = open (temp_file.c_str(), O_CREAT | O_WRONLY, mode); + assert(fd != -1); + close(fd); + + struct stat st; + assert(stat(temp_file.c_str(), &st) == 0); + + // Mask st_mode to get permission bits only + assert((st.st_mode & 0777) == mode); + + auto res = fs::remove (temp_file); + assert (res); +} + +void test_fcntlFlockDiesWhenRealtime() +{ + namespace fs = std::filesystem; + const fs::path temp_file = std::tmpnam (nullptr); + int fd = creat(temp_file.c_str(), S_IRUSR | S_IWUSR); + assert(fd != -1); + + auto func = [fd] { + struct flock lock{}; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = ::getpid(); + + assert(fcntl(fd, F_GETLK, &lock) == 0); + assert(lock.l_type == F_UNLCK); + }; + + close(fd); + std::remove (temp_file.c_str()); +} + +#pragma clang diagnostic pop + +int main() +{ + test_openCreatesFileWithProperMode(); + test_fcntlFlockDiesWhenRealtime(); + + return 0; +} +