diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 002b977a2e..4b3ebf809e 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -527,6 +527,10 @@ if (ENABLE_KERNEL_COVERAGE_COLLECTION) ../Kernel/Syscall.cpp ) set_source_files_properties(${KCOV_EXCLUDED_SOURCES} PROPERTIES COMPILE_FLAGS "-fno-sanitize-coverage=trace-pc") +elseif (ENABLE_USERSPACE_COVERAGE_COLLECTION) + # Disable checking open() pledges and the veil for coverage data when building userspace with coverage + # so that binaries can write out coverage data even with pledges/veil + add_compile_definitions(SKIP_PATH_VALIDATION_FOR_COVERAGE_INSTRUMENTATION) endif() # Kernel Undefined Behavior Sanitizer (KUBSAN) diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 3b20e78859..bea549d0c6 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -771,6 +771,13 @@ ErrorOr VirtualFileSystem::validate_path_against_process_veil(StringView p VERIFY(!path.contains("/../"sv) && !path.ends_with("/.."sv)); VERIFY(!path.contains("/./"sv) && !path.ends_with("/."sv)); +#ifdef SKIP_PATH_VALIDATION_FOR_COVERAGE_INSTRUMENTATION + // Skip veil validation against profile data when coverage is enabled for userspace + // so that all processes can write out coverage data even with veils in place + if (KLexicalPath::basename(path).ends_with(".profraw"sv)) + return {}; +#endif + auto& unveiled_path = find_matching_unveiled_path(path); if (unveiled_path.permissions() == UnveilAccess::None) { dbgln("Rejecting path '{}' since it hasn't been unveiled.", path); diff --git a/Kernel/Syscalls/open.cpp b/Kernel/Syscalls/open.cpp index 941722ba85..c8e7797f66 100644 --- a/Kernel/Syscalls/open.cpp +++ b/Kernel/Syscalls/open.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -27,19 +28,29 @@ ErrorOr Process::sys$open(Userspace use if (options & O_UNLINK_INTERNAL) return EINVAL; - if (options & O_WRONLY) - TRY(require_promise(Pledge::wpath)); - else if (options & O_RDONLY) - TRY(require_promise(Pledge::rpath)); + auto path = TRY(get_syscall_path_argument(params.path)); - if (options & O_CREAT) - TRY(require_promise(Pledge::cpath)); + // Disable checking open pledges when building userspace with coverage + // so that all processes can write out coverage data even with pledges + bool skip_pledge_verification = false; + +#ifdef SKIP_PATH_VALIDATION_FOR_COVERAGE_INSTRUMENTATION + if (KLexicalPath::basename(path->view()).ends_with(".profraw"sv)) + skip_pledge_verification = true; +#endif + if (!skip_pledge_verification) { + if (options & O_WRONLY) + TRY(require_promise(Pledge::wpath)); + else if (options & O_RDONLY) + TRY(require_promise(Pledge::rpath)); + + if (options & O_CREAT) + TRY(require_promise(Pledge::cpath)); + } // Ignore everything except permission bits. mode &= 0777; - auto path = TRY(get_syscall_path_argument(params.path)); - dbgln_if(IO_DEBUG, "sys$open(dirfd={}, path='{}', options={}, mode={})", dirfd, path->view(), options, mode); auto fd_allocation = TRY(allocate_fd());