Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,43 @@ INTERCEPTOR(int, mkfifo, const char *pathname, mode_t mode) {
return REAL(mkfifo)(pathname, mode);
}

#if SANITIZER_APPLE
#define INT_TYPE_SYSCALL int
#else
#define INT_TYPE_SYSCALL long
#endif

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
INTERCEPTOR(INT_TYPE_SYSCALL, syscall, INT_TYPE_SYSCALL number, ...) {
__rtsan_notify_intercepted_call("syscall");

va_list args;
va_start(args, number);

// the goal is to pick something large enough to hold all syscall args
// see fcntl for more discussion and why we always pull all 6 args
using arg_type = unsigned long;
arg_type arg1 = va_arg(args, arg_type);
arg_type arg2 = va_arg(args, arg_type);
arg_type arg3 = va_arg(args, arg_type);
arg_type arg4 = va_arg(args, arg_type);
arg_type arg5 = va_arg(args, arg_type);
arg_type arg6 = va_arg(args, arg_type);

// these are various examples of things that COULD be passed
static_assert(sizeof(arg_type) >= sizeof(off_t));
static_assert(sizeof(arg_type) >= sizeof(struct flock *));
static_assert(sizeof(arg_type) >= sizeof(const char *));
static_assert(sizeof(arg_type) >= sizeof(int));
static_assert(sizeof(arg_type) >= sizeof(unsigned long));

va_end(args);

return REAL(syscall)(number, arg1, arg2, arg3, arg4, arg5, arg6);
}
#pragma clang diagnostic pop

// Preinit
void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(calloc);
Expand Down Expand Up @@ -918,6 +955,8 @@ void __rtsan::InitializeInterceptors() {

INTERCEPT_FUNCTION(pipe);
INTERCEPT_FUNCTION(mkfifo);

INTERCEPT_FUNCTION(syscall);
}

#endif // SANITIZER_POSIX
17 changes: 17 additions & 0 deletions compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>

Expand Down Expand Up @@ -1090,4 +1091,20 @@ TEST(TestRtsanInterceptors, PipeDiesWhenRealtime) {
ExpectNonRealtimeSurvival(Func);
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
TEST(TestRtsanInterceptors, SyscallDiesWhenRealtime) {
auto Func = []() { syscall(SYS_getpid); };
ExpectRealtimeDeath(Func, "syscall");
ExpectNonRealtimeSurvival(Func);
}

TEST(TestRtsanInterceptors, GetPidReturnsSame) {
int pid = syscall(SYS_getpid);
EXPECT_THAT(pid, Ne(-1));

EXPECT_THAT(getpid(), Eq(pid));
}
#pragma clang diagnostic pop

#endif // SANITIZER_POSIX
78 changes: 78 additions & 0 deletions compiler-rt/test/rtsan/syscall.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// RUN: %clangxx -fsanitize=realtime %s -o %t
// RUN: %env_rtsan_opts="halt_on_error=false" %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-RTSAN,CHECK

// RUN: %clangxx %s -o %t
// RUN: %run %t 2>&1 | FileCheck %s

// UNSUPPORTED: ios

// Intent: Ensure the `syscall` call behaves in the same way with/without the
// sanitizer disabled

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

const char *GetTemporaryFilePath() { return "/tmp/rtsan_syscall_test.txt"; }

void custom_assert(bool condition, const char *message) {
if (!condition) {
fprintf(stderr, "ASSERTION FAILED: %s\n", message);
exit(1);
}
}

class ScopedFileCleanup {
public:
[[nodiscard]] ScopedFileCleanup() = default;
~ScopedFileCleanup() {
if (access(GetTemporaryFilePath(), F_OK) != -1)
unlink(GetTemporaryFilePath());
}
};

// Apple has deprecated `syscall`, ignore that error
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
int main() [[clang::nonblocking]] {
ScopedFileCleanup cleanup;

{
int fd = syscall(SYS_openat, AT_FDCWD, GetTemporaryFilePath(),
O_CREAT | O_WRONLY, 0644);

custom_assert(fd != -1, "Failed to open file - write");

int written = syscall(SYS_write, fd, "Hello, world!", 13);
custom_assert(written == 13, "Failed to write to file");

custom_assert(syscall(SYS_close, fd) == 0, "Failed to close file - write");
}

{
int fd = syscall(SYS_openat, AT_FDCWD, GetTemporaryFilePath(), O_RDONLY);
custom_assert(fd != -1, "Failed to open file - read");

char buffer[13];
int read = syscall(SYS_read, fd, buffer, 13);
custom_assert(read == 13, "Failed to read from file");

custom_assert(memcmp(buffer, "Hello, world!", 13) == 0,
"Read data does not match written data");

custom_assert(syscall(SYS_close, fd) == 0, "Failed to close file - read");
}

unlink(GetTemporaryFilePath());
printf("DONE\n");
}
#pragma clang diagnostic pop

// CHECK-NOT: ASSERTION FAILED
// CHECK-RTSAN-COUNT-6: Intercepted call to real-time unsafe function `syscall`

// CHECK: DONE