diff --git a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp index c7c6ab649..792114c7d 100644 --- a/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp +++ b/source/plugins/sandbox_plugin/source/sandbox_plugin.cpp @@ -32,8 +32,22 @@ /* Error messages */ #define SANDBOX_INITIALIZE_ERROR "Sandbox plugin failed to initialize a context" #define SANDBOX_UNAME_ERROR "Sandbox plugin failed to set uname syscall permissions" +#define SANDBOX_IO_ERROR "Sandbox plugin failed to set io syscalls permissions" +#define SANDBOX_SOCKETS_ERROR "Sandbox plugin failed to set sockets syscalls permissions" +#define SANDBOX_IPC_ERROR "Sandbox plugin failed to set IPC syscalls permissions" +#define SANDBOX_PROCESS_ERROR "Sandbox plugin failed to set process syscalls permissions" +#define SANDBOX_FILESYSTEMS_ERROR "Sandbox plugin failed to set filesystems syscalls permissions" +#define SANDBOX_TIME_ERROR "Sandbox plugin failed to set time syscalls permissions" +#define SANDBOX_MEMORY_ERROR "Sandbox plugin failed to set memory syscalls permissions" +#define SANDBOX_SIGNALS_ERROR "Sandbox plugin failed to set signals syscalls permissions" #define SANDBOX_DESTROY_ERROR "Sandbox plugin failed to destroy a context" +void add_syscalls_to_seccomp(scmp_filter_ctx ctx, const int* syscalls, const int action, size_t num_syscalls) { + for (long unsigned int i = 0; i < num_syscalls; i++) { + seccomp_rule_add(ctx, action, syscalls[i], 0); + } +} + void *sandbox_initialize(size_t argc, void *args[], void *data) { scmp_filter_ctx ctx; @@ -68,6 +82,325 @@ void *sandbox_uname(size_t argc, void *args[], void *data) return metacall_value_create_int(0); } +/* [Note] This function shouldn't be called to disable io, because metacall's basic operation is loading which is io operation */ +void *sandbox_io(size_t argc, void *args[], void *data) +{ + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_IO_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(brk), + SCMP_SYS(read), + SCMP_SYS(write), + SCMP_SYS(open), + SCMP_SYS(close), + SCMP_SYS(lseek), + SCMP_SYS(dup), + SCMP_SYS(dup2), + SCMP_SYS(dup3), + SCMP_SYS(pipe), + SCMP_SYS(select), + SCMP_SYS(poll), + SCMP_SYS(fcntl), + SCMP_SYS(ioctl), + SCMP_SYS(readv), + SCMP_SYS(writev), + SCMP_SYS(send), + SCMP_SYS(recv), + SCMP_SYS(sendto), + SCMP_SYS(recvfrom), + SCMP_SYS(sendmsg), + SCMP_SYS(recvmsg), + SCMP_SYS(fsync), + SCMP_SYS(fdatasync) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_sockets(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_SOCKETS_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(socket), // It is primarily associated to networking + SCMP_SYS(bind), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(listen), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(accept), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(connect), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(send), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(recv), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(sendto), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(recvfrom), // TODO: Check if this is needed, because it is also used for unix sockets (IPC) + SCMP_SYS(shutdown), // It is primarily associated to networking + SCMP_SYS(getpeername), // It is primarily associated to networking + SCMP_SYS(socketpair), // It is primarily associated to networking + SCMP_SYS(setsockopt) // It is primarily associated to networking + // SCMP_SYS(select), // Shouldn't be needed because it is used for file descriptors too + // SCMP_SYS(poll), // Shouldn't be needed because it is used for file descriptors too + // SCMP_SYS(fcntl), // Shouldn't be needed because it is used for file descriptors too + // SCMP_SYS(ioctl) // Shouldn't be needed because it is used for file descriptors too + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_ipc(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_IPC_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(shmget), + SCMP_SYS(shmat), + SCMP_SYS(shmdt), + SCMP_SYS(shmctl), + SCMP_SYS(msgget), + SCMP_SYS(msgsnd), + SCMP_SYS(msgrcv), + SCMP_SYS(msgctl), + SCMP_SYS(semget), + SCMP_SYS(semop), + SCMP_SYS(semctl) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_process(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_PROCESS_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(fork), + SCMP_SYS(vfork), + SCMP_SYS(clone), + SCMP_SYS(execve), + SCMP_SYS(wait4), + SCMP_SYS(waitpid), + SCMP_SYS(waitid), + SCMP_SYS(exit), + SCMP_SYS(exit_group), + SCMP_SYS(kill), + SCMP_SYS(getpid), + SCMP_SYS(getppid), + SCMP_SYS(setsid), + SCMP_SYS(setpgid), + SCMP_SYS(nice), + SCMP_SYS(sched_yield), + SCMP_SYS(setpriority), + SCMP_SYS(getpriority), + SCMP_SYS(getpgid), + SCMP_SYS(setsid) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_filesystems(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_FILESYSTEMS_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(access), + SCMP_SYS(faccessat), + SCMP_SYS(chdir), + SCMP_SYS(fchdir), + SCMP_SYS(chroot), + SCMP_SYS(fchmod), + SCMP_SYS(fchmodat), + SCMP_SYS(chown), + SCMP_SYS(fchown), + SCMP_SYS(fchownat), + SCMP_SYS(lchown), + SCMP_SYS(fcntl), + SCMP_SYS(ioctl), + SCMP_SYS(link), + SCMP_SYS(linkat), + SCMP_SYS(unlink), + SCMP_SYS(unlinkat), + SCMP_SYS(mkdir), + SCMP_SYS(mkdirat), + SCMP_SYS(rmdir), + SCMP_SYS(rename), + SCMP_SYS(renameat), + SCMP_SYS(symlink), + SCMP_SYS(symlinkat), + SCMP_SYS(readlink), + SCMP_SYS(readlinkat), + SCMP_SYS(truncate), + SCMP_SYS(ftruncate), + SCMP_SYS(stat), + SCMP_SYS(lstat), + SCMP_SYS(fstat), + SCMP_SYS(statfs), + SCMP_SYS(statfs64), + SCMP_SYS(fstatfs), + SCMP_SYS(fstatfs64), + SCMP_SYS(umount), + SCMP_SYS(umount2), + SCMP_SYS(mount), + SCMP_SYS(mount), + SCMP_SYS(mount) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_time(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_TIME_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(time), + SCMP_SYS(gettimeofday), + SCMP_SYS(settimeofday), + SCMP_SYS(clock_gettime), + SCMP_SYS(clock_settime), + SCMP_SYS(clock_getres), + SCMP_SYS(clock_nanosleep), + SCMP_SYS(nanosleep), + SCMP_SYS(stime), + SCMP_SYS(adjtimex), + SCMP_SYS(timer_create), + SCMP_SYS(timer_settime), + SCMP_SYS(timer_gettime), + SCMP_SYS(timer_getoverrun), + SCMP_SYS(timer_delete), + SCMP_SYS(timerfd_create), + SCMP_SYS(timerfd_settime), + SCMP_SYS(timerfd_gettime) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_memory(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_MEMORY_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(mmap), + SCMP_SYS(munmap), + SCMP_SYS(mprotect), + SCMP_SYS(brk), + SCMP_SYS(mincore), + SCMP_SYS(madvise), + SCMP_SYS(mlock), + SCMP_SYS(munlock), + SCMP_SYS(mlockall), + SCMP_SYS(munlockall), + SCMP_SYS(getrlimit), + SCMP_SYS(setrlimit), + SCMP_SYS(getrusage) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + +void *sandbox_signals(size_t argc, void *args[], void *data) +{ + + scmp_filter_ctx ctx; + + /* Validate function parameters */ + EXTENSION_FUNCTION_CHECK(SANDBOX_SIGNALS_ERROR, METACALL_PTR, METACALL_BOOL); + + ctx = metacall_value_to_ptr(args[0]); + + const int syscalls[] = { + SCMP_SYS(kill), + SCMP_SYS(tgkill), + SCMP_SYS(tkill), + SCMP_SYS(sigaction), + SCMP_SYS(sigprocmask), + SCMP_SYS(sigpending), + SCMP_SYS(sigsuspend), + SCMP_SYS(sigreturn), + SCMP_SYS(rt_sigaction), + SCMP_SYS(rt_sigprocmask), + SCMP_SYS(rt_sigpending), + SCMP_SYS(rt_sigsuspend), + SCMP_SYS(rt_sigreturn), + SCMP_SYS(rt_tgsigqueueinfo), + SCMP_SYS(rt_sigtimedwait), + SCMP_SYS(rt_sigqueueinfo) + }; + + add_syscalls_to_seccomp(ctx, syscalls, SANDBOX_ACTION(args[1]), sizeof(syscalls) / sizeof(syscalls[0])); + + seccomp_load(ctx); + + return metacall_value_create_int(0); +} + void *sandbox_destroy(size_t argc, void *args[], void *data) { scmp_filter_ctx ctx; @@ -106,6 +439,14 @@ int sandbox_plugin(void *loader, void *handle, void *context) EXTENSION_FUNCTION(METACALL_PTR, sandbox_initialize); EXTENSION_FUNCTION(METACALL_INT, sandbox_uname, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_io, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_sockets, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_ipc, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_process, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_filesystems, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_time, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_memory, METACALL_PTR, METACALL_BOOL); + EXTENSION_FUNCTION(METACALL_INT, sandbox_signals, METACALL_PTR, METACALL_BOOL); EXTENSION_FUNCTION(METACALL_INT, sandbox_destroy, METACALL_PTR); #if 0 /* TODO: Fork safety */ diff --git a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp index ffb4e7dfa..897072d97 100644 --- a/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp +++ b/source/tests/metacall_sandbox_plugin_test/source/metacall_sandbox_plugin_test.cpp @@ -23,6 +23,7 @@ #include #include + #include void invalid_syscall(void) @@ -32,6 +33,168 @@ void invalid_syscall(void) printf("%s\n", data.sysname); } +void invalid_io_syscall(void *sandbox_ctx, void *handle) { + /* Disable io syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_io", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + printf("Invalid IO syscall\n"); +} + +#include + +void invalid_sockets_syscall() { + int fd = socket(AF_INET, SOCK_STREAM, 0); + close(fd); +} + +#include +#include + +void invalid_ipc_syscall() { + // Create a shared memory segment + int shm_id = shmget(1234, 1024, IPC_CREAT | 0666); + if (shm_id == -1) { + perror("shmget"); + exit(EXIT_FAILURE); + } + + // Attach the shared memory segment to the process's address space + void* shm_addr = shmat(shm_id, NULL, 0); + if (shm_addr == (void*)-1) { + perror("shmat"); + exit(EXIT_FAILURE); + } + + // Write data to shared memory + const char* message = "Hello, Shared Memory!"; + strncpy((char*)shm_addr, message, 1024); + + printf("Data written to shared memory: %s\n", (char*)shm_addr); + + // Detach the shared memory segment + if (shmdt(shm_addr) == -1) { + perror("shmdt"); + exit(EXIT_FAILURE); + } + + // Remove the shared memory segment + if (shmctl(shm_id, IPC_RMID, NULL) == -1) { + perror("shmctl"); + exit(EXIT_FAILURE); + } +} + +#include +#include + +void invalid_process_syscall(void *sandbox_ctx, void *handle) { + /* Disable process syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_process", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + pid_t pid = fork(); + + if (pid < 0) { + perror("fork"); + exit(EXIT_FAILURE); + } + + if (pid == 0) { + // Child process + exit(EXIT_SUCCESS); // Exit immediately + } else { + // Parent process + int status; + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + exit(EXIT_FAILURE); + } + } +} + +#include +#include + +void invalid_filesystems_syscall(void *sandbox_ctx, void *handle) { + /* Disable filesystems syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_filesystems", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + int fd = open("/tmp/testfile", O_RDONLY); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + + close(fd); +} + +#include + +void invalid_time_syscall() { + sleep(1); +} + +#include + +void invalid_memory_syscall(void *sandbox_ctx, void *handle) { + /* Disable memory syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_memory", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + void* addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (addr == MAP_FAILED) { + perror("mmap"); + exit(EXIT_FAILURE); + } + munmap(addr, 4096); +} + +#include + +void invalid_signals_syscall() { + if (signal(SIGINT, SIG_IGN) == SIG_ERR) { + perror("signal"); + exit(EXIT_FAILURE); + } +} class metacall_sandbox_plugin_test : public testing::Test { protected: @@ -108,3 +271,344 @@ TEST_F(metacall_sandbox_plugin_test, DefaultConstructor) EXPECT_EQ((int)0, (int)metacall_destroy()); } + +/* [Note] This test blocks all the gtest context, so you should comment it to allow testing for other test cases */ +TEST_F(metacall_sandbox_plugin_test, SANDBOX_IO_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Generate a syscall exception when trying to execute fopen */ + ASSERT_EXIT({ invalid_io_syscall(sandbox_ctx, handle); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_SOCKETS_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Disable sockets syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_sockets", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + /* Generate a syscall exception when trying to execute socket */ + ASSERT_EXIT({ invalid_sockets_syscall(); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_IPC_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Disable IPC syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_ipc", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + /* Generate a syscall exception when trying to execute IPC operation */ + ASSERT_EXIT({ invalid_ipc_syscall(); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_PROCESS_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Generate a syscall exception when trying to execute process operation */ + ASSERT_EXIT({ invalid_process_syscall(sandbox_ctx, handle); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_FILESYSTEMS_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Generate a syscall exception when trying to execute file systems operation */ + ASSERT_EXIT({ invalid_filesystems_syscall(sandbox_ctx, handle); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_TIME_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Disable Time syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_time", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + /* Generate a syscall exception when trying to execute time operation */ + ASSERT_EXIT({ invalid_time_syscall(); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_MEMORY_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Generate a syscall exception when trying to execute memory operation */ + ASSERT_EXIT({ invalid_memory_syscall(sandbox_ctx, handle); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} + +TEST_F(metacall_sandbox_plugin_test, SANDBOX_SIGNALS_DISABLE_TEST) +{ + ASSERT_EQ((int)0, (int)metacall_initialize()); + + void *sandbox_ctx, *handle = metacall_plugin_extension(); + + /* Initialize sandboxing */ + { + void *args[1] = { metacall_value_create_bool(1L) /* Allow */ }; + + sandbox_ctx = metacallhv_s(handle, "sandbox_initialize", args, 1); + + EXPECT_NE((void *)NULL, (void *)sandbox_ctx); + EXPECT_NE((void *)metacall_value_to_ptr(sandbox_ctx), (void *)NULL); + + metacall_value_destroy(args[0]); + } + + /* Disable IPC syscall */ + { + void *args[2] = { sandbox_ctx, metacall_value_create_bool(0L) /* Kill */ }; + + void *ret = metacallhv_s(handle, "sandbox_signals", args, 2); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + metacall_value_destroy(args[1]); + } + + /* Generate a syscall exception when trying to execute signals operation */ + ASSERT_EXIT({ invalid_signals_syscall(); }, testing::KilledBySignal(SIGSYS), ""); + + /* Destroy sandboxing */ + { + void *args[1] = { sandbox_ctx }; + + void *ret = metacallhv_s(handle, "sandbox_destroy", args, 1); + + EXPECT_NE((void *)NULL, (void *)ret); + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(args[0]); + } + + EXPECT_EQ((int)0, (int)metacall_destroy()); +} \ No newline at end of file