diff --git a/c-grates/per-syscall-grates/close-grate/build.conf b/c-grates/per-syscall-grates/close-grate/build.conf new file mode 100644 index 0000000..4baaf6a --- /dev/null +++ b/c-grates/per-syscall-grates/close-grate/build.conf @@ -0,0 +1 @@ +ENTRY=close-grate.c diff --git a/c-grates/per-syscall-grates/close-grate/compile_grate.sh b/c-grates/per-syscall-grates/close-grate/compile_grate.sh new file mode 100755 index 0000000..9899f0e --- /dev/null +++ b/c-grates/per-syscall-grates/close-grate/compile_grate.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail + +cd "$(dirname "$0")" +lind_compile -s --compile-grate --output-dir grates src/close-grate.c diff --git a/c-grates/per-syscall-grates/close-grate/src/close-grate.c b/c-grates/per-syscall-grates/close-grate/src/close-grate.c new file mode 100644 index 0000000..62abe43 --- /dev/null +++ b/c-grates/per-syscall-grates/close-grate/src/close-grate.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +#define CLOSE_SYSCALL 3 + +int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t grateid, uint64_t arg1, + uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, + uint64_t arg3, uint64_t arg3cage, uint64_t arg4, + uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, + uint64_t arg6, uint64_t arg6cage) { + if (fn_ptr_uint == 0) { + return -1; + } + + int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t) = + (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t))(uintptr_t)fn_ptr_uint; + + return fn(grateid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage); +} + +int close_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, + uint64_t arg6cage) { + + return make_threei_call(CLOSE_SYSCALL, 0, cageid, arg1cage, arg1, + arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage, 0); +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + int grateid = getpid(); + + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + exit(EXIT_FAILURE); + } else if (pid == 0) { + int cageid = getpid(); + + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&close_grate; + int ret = register_handler(cageid, CLOSE_SYSCALL, grateid, fn_ptr_addr); + + if (execv(argv[1], &argv[1]) == -1) { + perror("execv failed"); + exit(EXIT_FAILURE); + } + } + + int status; + while (wait(&status) > 0) { + printf("[Grate|close] terminated, status: %d\n", status); + } + + return 0; +} diff --git a/c-grates/per-syscall-grates/close-grate/test/close-test.c b/c-grates/per-syscall-grates/close-grate/test/close-test.c new file mode 100644 index 0000000..e502b9d --- /dev/null +++ b/c-grates/per-syscall-grates/close-grate/test/close-test.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include + +int main() { + int fd; + const char *filename = "testfile.txt"; + + // 1. Open a file to get a valid fd + fd = open(filename, O_CREAT | O_RDWR, 0644); + assert(fd >= 0); + + // 2. Close should succeed + int ret = close(fd); + assert(ret == 0); + + // 3. Closing again should fail (EBADF) + ret = close(fd); + assert(ret == -1); + assert(errno == EBADF); + + // 4. Closing an invalid fd should fail + ret = close(-1); + assert(ret == -1); + assert(errno == EBADF); + + // 5. Cleanup: remove the file + ret = unlink(filename); + assert(ret == 0); + + printf("All close() tests passed.\n"); + return 0; +} diff --git a/c-grates/per-syscall-grates/geteuid-grate/build.conf b/c-grates/per-syscall-grates/geteuid-grate/build.conf new file mode 100644 index 0000000..7b82194 --- /dev/null +++ b/c-grates/per-syscall-grates/geteuid-grate/build.conf @@ -0,0 +1 @@ +ENTRY=geteuid-grate.c diff --git a/c-grates/per-syscall-grates/geteuid-grate/compile_grate.sh b/c-grates/per-syscall-grates/geteuid-grate/compile_grate.sh new file mode 100755 index 0000000..7a2b40d --- /dev/null +++ b/c-grates/per-syscall-grates/geteuid-grate/compile_grate.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail + +cd "$(dirname "$0")" +lind_compile -s --compile-grate --output-dir grates src/geteuid-grate.c diff --git a/c-grates/per-syscall-grates/geteuid-grate/src/geteuid-grate.c b/c-grates/per-syscall-grates/geteuid-grate/src/geteuid-grate.c new file mode 100644 index 0000000..54853c6 --- /dev/null +++ b/c-grates/per-syscall-grates/geteuid-grate/src/geteuid-grate.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +#define GETEUID_SYSCALL 107 + +int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t grateid, uint64_t arg1, + uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, + uint64_t arg3, uint64_t arg3cage, uint64_t arg4, + uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, + uint64_t arg6, uint64_t arg6cage) { + if (fn_ptr_uint == 0) { + return -1; + } + + int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t) = + (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t))(uintptr_t)fn_ptr_uint; + + return fn(grateid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage); +} + +int geteuid_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, + uint64_t arg6cage) { + + return make_threei_call(GETEUID_SYSCALL, 0, cageid, arg1cage, arg1, + arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage, 0); +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + int grateid = getpid(); + + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + exit(EXIT_FAILURE); + } else if (pid == 0) { + int cageid = getpid(); + + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&geteuid_grate; + int ret = register_handler(cageid, GETEUID_SYSCALL, grateid, fn_ptr_addr); + + if (execv(argv[1], &argv[1]) == -1) { + perror("execv failed"); + exit(EXIT_FAILURE); + } + } + + int status; + while (wait(&status) > 0) { + printf("[Grate|geteuid] terminated, status: %d\n", status); + } + + return 0; +} diff --git a/c-grates/per-syscall-grates/geteuid-grate/test/geteuid-test.c b/c-grates/per-syscall-grates/geteuid-grate/test/geteuid-test.c new file mode 100644 index 0000000..e627830 --- /dev/null +++ b/c-grates/per-syscall-grates/geteuid-grate/test/geteuid-test.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +int main() { + uid_t euid1, euid2; + + // 1. Multiple calls should be consistent + euid1 = geteuid(); + euid2 = geteuid(); + assert(euid1 == euid2); + + // 2. EUID should be non-negative + assert(euid1 >= 0); + + // 3. Save original IDs + uid_t ruid = getuid(); + uid_t orig_euid = euid1; + + // 4. Try changing effective UID (may fail if not permitted) + if (seteuid(ruid) == 0) { + uid_t new_euid = geteuid(); + assert(new_euid == ruid); + + // Restore original effective UID + int ret = seteuid(orig_euid); + assert(ret == 0); + + // Verify restoration + assert(geteuid() == orig_euid); + } else { + // If we can't change EUID, just note it + printf("Skipping seteuid() test (insufficient permissions)\n"); + } + + printf("geteuid() test passed (euid=%d)\n", orig_euid); + return 0; +} diff --git a/c-grates/per-syscall-grates/getpid-grate/build.conf b/c-grates/per-syscall-grates/getpid-grate/build.conf new file mode 100644 index 0000000..1e06b5a --- /dev/null +++ b/c-grates/per-syscall-grates/getpid-grate/build.conf @@ -0,0 +1 @@ +ENTRY=getpid-grate.c diff --git a/c-grates/per-syscall-grates/getpid-grate/compile_grate.sh b/c-grates/per-syscall-grates/getpid-grate/compile_grate.sh new file mode 100755 index 0000000..88d0fe8 --- /dev/null +++ b/c-grates/per-syscall-grates/getpid-grate/compile_grate.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail + +cd "$(dirname "$0")" +lind_compile -s --compile-grate --output-dir grates src/getpid-grate.c diff --git a/c-grates/per-syscall-grates/getpid-grate/src/getpid-grate.c b/c-grates/per-syscall-grates/getpid-grate/src/getpid-grate.c new file mode 100644 index 0000000..a245139 --- /dev/null +++ b/c-grates/per-syscall-grates/getpid-grate/src/getpid-grate.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +#define GETPID_SYSCALL 39 + +int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t grateid, uint64_t arg1, + uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, + uint64_t arg3, uint64_t arg3cage, uint64_t arg4, + uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, + uint64_t arg6, uint64_t arg6cage) { + if (fn_ptr_uint == 0) { + return -1; + } + + int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t) = + (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t))(uintptr_t)fn_ptr_uint; + + return fn(grateid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage); +} + +int getpid_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, + uint64_t arg6cage) { + + return make_threei_call(GETPID_SYSCALL, 0, cageid, arg1cage, arg1, + arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage, 0); +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + int grateid = getpid(); + + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + exit(EXIT_FAILURE); + } else if (pid == 0) { + int cageid = getpid(); + + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&getpid_grate; + int ret = register_handler(cageid, GETPID_SYSCALL, grateid, fn_ptr_addr); + + if (execv(argv[1], &argv[1]) == -1) { + perror("execv failed"); + exit(EXIT_FAILURE); + } + } + + int status; + while (wait(&status) > 0) { + printf("[Grate|getpid] terminated, status: %d\n", status); + } + + return 0; +} diff --git a/c-grates/per-syscall-grates/getpid-grate/test/getpid-test.c b/c-grates/per-syscall-grates/getpid-grate/test/getpid-test.c new file mode 100644 index 0000000..e4f3a64 --- /dev/null +++ b/c-grates/per-syscall-grates/getpid-grate/test/getpid-test.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +int main() { + pid_t pid1, pid2; + + // 1. Multiple calls should return the same PID + pid1 = getpid(); + pid2 = getpid(); + assert(pid1 == pid2); + + // 2. PID should be positive + assert(pid1 > 0); + + // 3. Fork and verify child has a different PID + pid_t child = fork(); + assert(child >= 0); + + if (child == 0) { + // Child process + pid_t child_pid = getpid(); + pid_t parent_pid = getppid(); + + assert(child_pid != pid1); // child PID differs from parent + assert(parent_pid == pid1); // parent PID matches original + + _exit(0); + } else { + // Parent process + int status; + waitpid(child, &status, 0); + assert(WIFEXITED(status)); + } + + printf("getpid() test passed (pid=%d)\n", pid1); + return 0; +} diff --git a/c-grates/per-syscall-grates/getuid-grate/build.conf b/c-grates/per-syscall-grates/getuid-grate/build.conf new file mode 100644 index 0000000..fe09698 --- /dev/null +++ b/c-grates/per-syscall-grates/getuid-grate/build.conf @@ -0,0 +1 @@ +ENTRY=getuid-grate.c diff --git a/c-grates/per-syscall-grates/getuid-grate/compile_grate.sh b/c-grates/per-syscall-grates/getuid-grate/compile_grate.sh new file mode 100755 index 0000000..d433605 --- /dev/null +++ b/c-grates/per-syscall-grates/getuid-grate/compile_grate.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -euo pipefail + +cd "$(dirname "$0")" +lind_compile -s --compile-grate --output-dir grates src/getuid-grate.c diff --git a/c-grates/per-syscall-grates/getuid-grate/src/getuid-grate.c b/c-grates/per-syscall-grates/getuid-grate/src/getuid-grate.c new file mode 100644 index 0000000..df40cd3 --- /dev/null +++ b/c-grates/per-syscall-grates/getuid-grate/src/getuid-grate.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include + +#define GETUID_SYSCALL 102 + +int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t grateid, uint64_t arg1, + uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, + uint64_t arg3, uint64_t arg3cage, uint64_t arg4, + uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, + uint64_t arg6, uint64_t arg6cage) { + if (fn_ptr_uint == 0) { + return -1; + } + + int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t) = + (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t))(uintptr_t)fn_ptr_uint; + + return fn(grateid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage); +} + +int getuid_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, + uint64_t arg6cage) { + + return make_threei_call(GETUID_SYSCALL, 0, cageid, arg1cage, arg1, + arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, + arg4cage, arg5, arg5cage, arg6, arg6cage, 0); +} + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + int grateid = getpid(); + + pid_t pid = fork(); + if (pid < 0) { + perror("fork failed"); + exit(EXIT_FAILURE); + } else if (pid == 0) { + int cageid = getpid(); + + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&getuid_grate; + int ret = register_handler(cageid, GETUID_SYSCALL, grateid, fn_ptr_addr); + + if (execv(argv[1], &argv[1]) == -1) { + perror("execv failed"); + exit(EXIT_FAILURE); + } + } + + int status; + while (wait(&status) > 0) { + printf("[Grate|getuid] terminated, status: %d\n", status); + } + + return 0; +} diff --git a/c-grates/per-syscall-grates/getuid-grate/test/getuid-test.c b/c-grates/per-syscall-grates/getuid-grate/test/getuid-test.c new file mode 100644 index 0000000..bd8e774 --- /dev/null +++ b/c-grates/per-syscall-grates/getuid-grate/test/getuid-test.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include + +int main() { + uid_t uid1, uid2; + + // 1. Call getuid() twice — should be consistent + uid1 = getuid(); + uid2 = getuid(); + assert(uid1 == uid2); + + // 2. UID should be non-negative + assert(uid1 >= 0); + + // 3. Compare with geteuid() in normal (non-setuid) case + uid_t euid = geteuid(); + if (uid1 != euid) { + printf("Note: real UID (%d) != effective UID (%d) (setuid context?)\n", + uid1, euid); + } + + printf("getuid() test passed (uid=%d)\n", uid1); + return 0; +}