From 6731b726983f0758142e660fa662c85eb9a3fa80 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Sun, 29 Dec 2024 15:10:37 +1300 Subject: [PATCH] Don't die when `is_privileged_executable` fails Resolves #3894 --- CMakeLists.txt | 2 ++ src/record_syscall.cc | 13 ++++++++----- src/test/fexecve.c | 23 +++++++++++++++++++++++ src/test/fexecve_memfd.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 src/test/fexecve.c create mode 100644 src/test/fexecve_memfd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bca572b5cc..b4384207ec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1068,6 +1068,8 @@ set(BASIC_TESTS fd_cleanup fd_tracking_across_threads fds_clean + fexecve + fexecve_memfd flock flock_ofd flock2 diff --git a/src/record_syscall.cc b/src/record_syscall.cc index ba409c7f671..22ce6a3efa4 100644 --- a/src/record_syscall.cc +++ b/src/record_syscall.cc @@ -5566,12 +5566,15 @@ static bool is_privileged_executable(RecordTask* t, const string& path) { return true; } } else { - ASSERT(t, errno == ENODATA || errno == ENOTSUP); - struct stat buf; - stat(path.c_str(), &buf); - if (buf.st_mode & (S_ISUID | S_ISGID)) { - return true; + if (errno == ENOENT) { + return false; } + ASSERT(t, errno == ENODATA || errno == ENOTSUP); + } + struct stat buf; + stat(path.c_str(), &buf); + if (buf.st_mode & (S_ISUID | S_ISGID)) { + return true; } return false; } diff --git a/src/test/fexecve.c b/src/test/fexecve.c new file mode 100644 index 00000000000..b34c2bde925 --- /dev/null +++ b/src/test/fexecve.c @@ -0,0 +1,23 @@ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include "util.h" + +int main(int argc, char* argv[]) { + test_assert(argc == 1 || (argc == 2 && !strcmp("self", argv[1]))); + + if (argc != 2) { + int fd = open("/proc/self/exe", O_RDONLY); + test_assert(fd >= 0); + char* new_args[] = { argv[0], "self", NULL }; + int ret = syscall(RR_execveat, fd, "", new_args, environ, AT_EMPTY_PATH); + if (ret < 0 && errno == ENOSYS) { + atomic_puts("execveat not supported, skipping test"); + atomic_puts("EXIT-SUCCESS"); + return 0; + } + test_assert("Not reached" && 0); + } + + atomic_puts("EXIT-SUCCESS"); + return 0; +} \ No newline at end of file diff --git a/src/test/fexecve_memfd.c b/src/test/fexecve_memfd.c new file mode 100644 index 00000000000..706d2b60b35 --- /dev/null +++ b/src/test/fexecve_memfd.c @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include "util.h" + +static void copy_file(int from_fd, int to_fd) { + char buf[4096]; + ssize_t ret; + + while ((ret = read(from_fd, buf, sizeof(buf))) > 0) { + test_assert(write(to_fd, buf, ret) == ret); + } + test_assert(ret == 0); +} + +int main(int argc, char* argv[]) { + test_assert(argc == 1 || (argc == 2 && !strcmp("self", argv[1]))); + + if (argc != 2) { + int fd = open("/proc/self/exe", O_RDONLY); + test_assert(fd >= 0); + int memfd = syscall(RR_memfd_create, "test", 0); + copy_file(fd, memfd); + char* new_args[] = { argv[0], "self", NULL }; + int ret = syscall(RR_execveat, memfd, "", new_args, environ, AT_EMPTY_PATH); + if (ret < 0 && errno == ENOSYS) { + atomic_puts("execveat not supported, skipping test"); + atomic_puts("EXIT-SUCCESS"); + return 0; + } + test_assert("Not reached" && 0); + } + + atomic_puts("EXIT-SUCCESS"); + return 0; +} \ No newline at end of file