[clang] [llvm] Sandboxing v2 (PR #165350)
Jan Svoboda via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 30 15:53:24 PDT 2025
https://github.com/jansvoboda11 updated https://github.com/llvm/llvm-project/pull/165350
>From ce13278e1df2649e7c0c889da4b9eafa258dde06 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:00:53 -0700
Subject: [PATCH 01/19] [llvm] Introduce IO sandboxing
---
llvm/CMakeLists.txt | 1 +
llvm/include/llvm/Config/llvm-config.h.cmake | 3 ++
llvm/include/llvm/Support/IOSandbox.h | 39 ++++++++++++++++++++
3 files changed, 43 insertions(+)
create mode 100644 llvm/include/llvm/Support/IOSandbox.h
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index c450ee5a3d72e..eba10b7a703dd 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -704,6 +704,7 @@ else()
option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON)
endif()
+option(LLVM_ENABLE_IO_SANDBOX "Enable IO sandboxing in supported tools" ${LLVM_ENABLE_ASSERTIONS})
option(LLVM_ENABLE_EXPENSIVE_CHECKS "Enable expensive checks" OFF)
set(LLVM_ABI_BREAKING_CHECKS "WITH_ASSERTS" CACHE STRING
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index 6488d6c01b5c6..9ac0115ee2184 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -126,6 +126,9 @@
* in non assert builds */
#cmakedefine01 LLVM_UNREACHABLE_OPTIMIZE
+/* Define if building LLVM with LLVM_ENABLE_IO_SANDBOX */
+#cmakedefine01 LLVM_ENABLE_IO_SANDBOX
+
/* Define to 1 if you have the DIA SDK installed, and to 0 if you don't. */
#cmakedefine01 LLVM_ENABLE_DIA_SDK
diff --git a/llvm/include/llvm/Support/IOSandbox.h b/llvm/include/llvm/Support/IOSandbox.h
new file mode 100644
index 0000000000000..ccd8af24273da
--- /dev/null
+++ b/llvm/include/llvm/Support/IOSandbox.h
@@ -0,0 +1,39 @@
+//===- IOSandbox.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_IOSANDBOX_H
+#define LLVM_SUPPORT_IOSANDBOX_H
+
+#ifdef LLVM_ENABLE_IO_SANDBOX
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SaveAndRestore.h"
+
+namespace llvm::sys::sandbox {
+inline thread_local bool Enabled = false;
+using ScopedSetting = SaveAndRestore<bool>;
+inline SaveAndRestore<bool> scopedEnable() { return {Enabled, true}; }
+inline SaveAndRestore<bool> scopedDisable() { return {Enabled, false}; }
+inline void violationIfEnabled() {
+ if (Enabled)
+ reportFatalInternalError("IO sandbox violation");
+}
+} // namespace llvm::sys::sandbox
+
+#else
+
+namespace llvm::sys::sandbox {
+using ScopedSetting = bool;
+inline ScopedSetting scopedEnable() { return true; }
+inline ScopedSetting scopedDisable() { return true; }
+inline void violationIfEnabled() {}
+} // namespace llvm::sys::sandbox
+
+#endif
+
+#endif
>From 150ed6ce111c5acdb9397eb8799dad7f74b24d53 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:01:48 -0700
Subject: [PATCH 02/19] [clang] Enable IO sandboxing in -cc1 and -cc1as
---
clang/lib/Driver/Job.cpp | 5 +++++
clang/tools/driver/cc1_main.cpp | 27 ++++++++++++++++++---------
clang/tools/driver/cc1as_main.cpp | 13 ++++++++++---
llvm/lib/Support/Signals.cpp | 4 ++++
4 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 715429bcd2096..e52d1069b4209 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Program.h"
@@ -426,6 +427,10 @@ int CC1Command::Execute(ArrayRef<std::optional<StringRef>> Redirects,
if (ExecutionFailed)
*ExecutionFailed = false;
+ // Enabling the sandbox here allows us to restore its previous state even when
+ // this cc1 invocation crashes.
+ [[maybe_unused]] auto EnableSandbox = llvm::sys::sandbox::scopedEnable();
+
llvm::CrashRecoveryContext CRC;
CRC.DumpStackAndCleanupOnFailure = true;
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 52cffa4ccbe1f..8a20c7df5f596 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -38,6 +38,7 @@
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
@@ -272,7 +273,11 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
/// Create the actual file system.
- Clang->createVirtualFileSystem(llvm::vfs::getRealFileSystem(), DiagsBuffer);
+ auto VFS = [] {
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+ return llvm::vfs::getRealFileSystem();
+ }();
+ Clang->createVirtualFileSystem(std::move(VFS), DiagsBuffer);
// Create the actual diagnostics engine.
Clang->createDiagnostics();
@@ -302,15 +307,19 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
// If any timers were active but haven't been destroyed yet, print their
// results now. This happens in -disable-free mode.
- std::unique_ptr<raw_ostream> IOFile = llvm::CreateInfoOutputFile();
- if (Clang->getCodeGenOpts().TimePassesJson) {
- *IOFile << "{\n";
- llvm::TimerGroup::printAllJSONValues(*IOFile, "");
- *IOFile << "\n}\n";
- } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) {
- llvm::TimerGroup::printAll(*IOFile);
+ {
+ // This isn't a formal input or output of the compiler.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+ std::unique_ptr<raw_ostream> IOFile = llvm::CreateInfoOutputFile();
+ if (Clang->getCodeGenOpts().TimePassesJson) {
+ *IOFile << "{\n";
+ llvm::TimerGroup::printAllJSONValues(*IOFile, "");
+ *IOFile << "\n}\n";
+ } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) {
+ llvm::TimerGroup::printAll(*IOFile);
+ }
+ llvm::TimerGroup::clearAll();
}
- llvm::TimerGroup::clearAll();
if (llvm::timeTraceProfilerEnabled()) {
if (auto profilerOutput = Clang->createOutputFile(
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index 50da2f8449a22..589b7304e8565 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
@@ -425,8 +426,11 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
if (!TheTarget)
return Diags.Report(diag::err_target_unknown_triple) << Opts.Triple.str();
- ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
- MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = [&] {
+ // FIXME(sandboxing): Make this a proper input file.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+ return MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
+ }();
if (std::error_code EC = Buffer.getError()) {
return Diags.Report(diag::err_fe_error_reading)
@@ -672,7 +676,10 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
DiagClient->setPrefix("clang -cc1as");
DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagClient);
- auto VFS = vfs::getRealFileSystem();
+ auto VFS = [] {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+ return vfs::getRealFileSystem();
+ }();
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp
index f8a14a45ddc3e..786c4576f13e3 100644
--- a/llvm/lib/Support/Signals.cpp
+++ b/llvm/lib/Support/Signals.cpp
@@ -23,6 +23,7 @@
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -95,6 +96,9 @@ CallBacksToRun() {
// Signal-safe.
void sys::RunSignalHandlers() {
+ // Let's not interfere with stack trace symbolication and friends.
+ [[maybe_unused]] auto BypassSandbox = sandbox::scopedDisable();
+
for (CallbackAndCookie &RunMe : CallBacksToRun()) {
auto Expected = CallbackAndCookie::Status::Initialized;
auto Desired = CallbackAndCookie::Status::Executing;
>From 2c7996ef19ea14092d713a6a69738c4ef4e710e5 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:09:57 -0700
Subject: [PATCH 03/19] [Support] Disallow `MemoryBuffer::getFile*()` in IO
sandbox
---
llvm/lib/Support/MemoryBuffer.cpp | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp
index 1c4645ad83641..c64d88d9f5067 100644
--- a/llvm/lib/Support/MemoryBuffer.cpp
+++ b/llvm/lib/Support/MemoryBuffer.cpp
@@ -161,6 +161,8 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFileOrSTDIN(const Twine &Filename, bool IsText,
bool RequiresNullTerminator,
std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
SmallString<256> NameBuf;
StringRef NameRef = Filename.toStringRef(NameBuf);
@@ -174,6 +176,8 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize,
uint64_t Offset, bool IsVolatile,
std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
return getFileAux<MemoryBuffer>(FilePath, MapSize, Offset, /*IsText=*/false,
/*RequiresNullTerminator=*/false, IsVolatile,
Alignment);
@@ -258,6 +262,8 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFile(const Twine &Filename, bool IsText,
bool RequiresNullTerminator, bool IsVolatile,
std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
return getFileAux<MemoryBuffer>(Filename, /*MapSize=*/-1, /*Offset=*/0,
IsText, RequiresNullTerminator, IsVolatile,
Alignment);
@@ -288,6 +294,8 @@ getFileAux(const Twine &Filename, uint64_t MapSize, uint64_t Offset,
ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
WritableMemoryBuffer::getFile(const Twine &Filename, bool IsVolatile,
std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
return getFileAux<WritableMemoryBuffer>(
Filename, /*MapSize=*/-1, /*Offset=*/0, /*IsText=*/false,
/*RequiresNullTerminator=*/false, IsVolatile, Alignment);
@@ -297,6 +305,8 @@ ErrorOr<std::unique_ptr<WritableMemoryBuffer>>
WritableMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
uint64_t Offset, bool IsVolatile,
std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
return getFileAux<WritableMemoryBuffer>(
Filename, MapSize, Offset, /*IsText=*/false,
/*RequiresNullTerminator=*/false, IsVolatile, Alignment);
@@ -455,6 +465,8 @@ getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize,
ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) {
+ sys::sandbox::violationIfEnabled();
+
return getReadWriteFile(Filename, FileSize, FileSize, 0);
}
@@ -462,6 +474,8 @@ WriteThroughMemoryBuffer::getFile(const Twine &Filename, int64_t FileSize) {
ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>>
WriteThroughMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize,
uint64_t Offset) {
+ sys::sandbox::violationIfEnabled();
+
return getReadWriteFile(Filename, -1, MapSize, Offset);
}
@@ -554,6 +568,8 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getOpenFile(sys::fs::file_t FD, const Twine &Filename,
uint64_t FileSize, bool RequiresNullTerminator,
bool IsVolatile, std::optional<Align> Alignment) {
+ sys::sandbox::violationIfEnabled();
+
return getOpenFileImpl<MemoryBuffer>(FD, Filename, FileSize, FileSize, 0,
RequiresNullTerminator, IsVolatile,
Alignment);
@@ -563,11 +579,16 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getOpenFileSlice(
sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize, int64_t Offset,
bool IsVolatile, std::optional<Align> Alignment) {
assert(MapSize != uint64_t(-1));
+
+ sys::sandbox::violationIfEnabled();
+
return getOpenFileImpl<MemoryBuffer>(FD, Filename, -1, MapSize, Offset, false,
IsVolatile, Alignment);
}
ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
+ sys::sandbox::violationIfEnabled();
+
// Read in all of the data from stdin, we cannot mmap stdin.
//
// FIXME: That isn't necessarily true, we should try to mmap stdin and
@@ -579,6 +600,8 @@ ErrorOr<std::unique_ptr<MemoryBuffer>> MemoryBuffer::getSTDIN() {
ErrorOr<std::unique_ptr<MemoryBuffer>>
MemoryBuffer::getFileAsStream(const Twine &Filename) {
+ sys::sandbox::violationIfEnabled();
+
Expected<sys::fs::file_t> FDOrErr =
sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None);
if (!FDOrErr)
>From 670cf8cc85f67d5931135d10743ecc6b33cdaa80 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:12:29 -0700
Subject: [PATCH 04/19] [Support] Disallow `vfs::{create,get}RealFileSystem()`
in IO sandbox
---
llvm/lib/Support/VirtualFileSystem.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index c754b30d8de4a..547e6c9abf57b 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -31,6 +31,7 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileSystem/UniqueID.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SMLoc.h"
@@ -399,10 +400,14 @@ void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type,
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
static IntrusiveRefCntPtr<FileSystem> FS =
makeIntrusiveRefCnt<RealFileSystem>(true);
+ sys::sandbox::violationIfEnabled();
+
return FS;
}
std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
+ sys::sandbox::violationIfEnabled();
+
return std::make_unique<RealFileSystem>(false);
}
>From f4242fcb79d1b8c6396afbbb0d563309c41024cc Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:35:26 -0700
Subject: [PATCH 05/19] [Support] Disallow input `sys::fs` APIs in IO sandbox
---
llvm/include/llvm/Support/FileSystem.h | 11 +++++++
llvm/lib/Support/Path.cpp | 20 +++++++++++++
llvm/lib/Support/Unix/Path.inc | 37 ++++++++++++++++++++++++
llvm/lib/Support/Windows/Path.inc | 40 ++++++++++++++++++++++++--
4 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h
index cf2a8104ac813..fa8753d146e22 100644
--- a/llvm/include/llvm/Support/FileSystem.h
+++ b/llvm/include/llvm/Support/FileSystem.h
@@ -36,6 +36,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem/UniqueID.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
@@ -1447,6 +1448,8 @@ class directory_iterator {
explicit directory_iterator(const Twine &path, std::error_code &ec,
bool follow_symlinks = true)
: FollowSymlinks(follow_symlinks) {
+ sandbox::violationIfEnabled();
+
State = std::make_shared<detail::DirIterState>();
SmallString<128> path_storage;
ec = detail::directory_iterator_construct(
@@ -1456,6 +1459,8 @@ class directory_iterator {
explicit directory_iterator(const directory_entry &de, std::error_code &ec,
bool follow_symlinks = true)
: FollowSymlinks(follow_symlinks) {
+ sandbox::violationIfEnabled();
+
State = std::make_shared<detail::DirIterState>();
ec = detail::directory_iterator_construct(
*State, de.path(), FollowSymlinks);
@@ -1466,6 +1471,8 @@ class directory_iterator {
// No operator++ because we need error_code.
directory_iterator &increment(std::error_code &ec) {
+ sandbox::violationIfEnabled();
+
ec = directory_iterator_increment(*State);
return *this;
}
@@ -1511,6 +1518,8 @@ class recursive_directory_iterator {
bool follow_symlinks = true)
: State(std::make_shared<detail::RecDirIterState>()),
Follow(follow_symlinks) {
+ sandbox::violationIfEnabled();
+
State->Stack.push_back(directory_iterator(path, ec, Follow));
if (State->Stack.back() == directory_iterator())
State.reset();
@@ -1518,6 +1527,8 @@ class recursive_directory_iterator {
// No operator++ because we need error_code.
recursive_directory_iterator &increment(std::error_code &ec) {
+ sandbox::violationIfEnabled();
+
const directory_iterator end_itr = {};
if (State->HasNoPushRequest)
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 3e066665f4155..16d506d21927f 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -834,6 +834,8 @@ bool remove_dots(SmallVectorImpl<char> &the_path, bool remove_dot_dot,
namespace fs {
std::error_code getUniqueID(const Twine Path, UniqueID &Result) {
+ sandbox::violationIfEnabled();
+
file_status Status;
std::error_code EC = status(Path, Status);
if (EC)
@@ -953,6 +955,8 @@ getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
}
std::error_code make_absolute(SmallVectorImpl<char> &path) {
+ sandbox::violationIfEnabled();
+
if (path::is_absolute(path))
return {};
@@ -1045,6 +1049,8 @@ std::error_code copy_file(const Twine &From, int ToFD) {
}
ErrorOr<MD5::MD5Result> md5_contents(int FD) {
+ sandbox::violationIfEnabled();
+
MD5 Hash;
constexpr size_t BufSize = 4096;
@@ -1065,6 +1071,8 @@ ErrorOr<MD5::MD5Result> md5_contents(int FD) {
}
ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path) {
+ sandbox::violationIfEnabled();
+
int FD;
if (auto EC = openFileForRead(Path, FD, OF_None))
return EC;
@@ -1094,6 +1102,8 @@ bool is_directory(const basic_file_status &status) {
}
std::error_code is_directory(const Twine &path, bool &result) {
+ sandbox::violationIfEnabled();
+
file_status st;
if (std::error_code ec = status(path, st))
return ec;
@@ -1106,6 +1116,8 @@ bool is_regular_file(const basic_file_status &status) {
}
std::error_code is_regular_file(const Twine &path, bool &result) {
+ sandbox::violationIfEnabled();
+
file_status st;
if (std::error_code ec = status(path, st))
return ec;
@@ -1118,6 +1130,8 @@ bool is_symlink_file(const basic_file_status &status) {
}
std::error_code is_symlink_file(const Twine &path, bool &result) {
+ sandbox::violationIfEnabled();
+
file_status st;
if (std::error_code ec = status(path, st, false))
return ec;
@@ -1132,6 +1146,8 @@ bool is_other(const basic_file_status &status) {
}
std::error_code is_other(const Twine &Path, bool &Result) {
+ sandbox::violationIfEnabled();
+
file_status FileStatus;
if (std::error_code EC = status(Path, FileStatus))
return EC;
@@ -1149,6 +1165,8 @@ void directory_entry::replace_filename(const Twine &Filename, file_type Type,
}
ErrorOr<perms> getPermissions(const Twine &Path) {
+ sandbox::violationIfEnabled();
+
file_status Status;
if (std::error_code EC = status(Path, Status))
return EC;
@@ -1173,6 +1191,8 @@ const char *mapped_file_region::const_data() const {
Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl<char> &Buffer,
ssize_t ChunkSize) {
+ sandbox::violationIfEnabled();
+
// Install a handler to truncate the buffer to the correct size on exit.
size_t Size = Buffer.size();
auto TruncateOnExit = make_scope_exit([&]() { Buffer.truncate(Size); });
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 0d991ead72416..ab4d2e33213a5 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -366,6 +366,8 @@ ErrorOr<space_info> disk_space(const Twine &Path) {
}
std::error_code current_path(SmallVectorImpl<char> &result) {
+ sandbox::violationIfEnabled();
+
result.clear();
const char *pwd = ::getenv("PWD");
@@ -399,6 +401,8 @@ std::error_code current_path(SmallVectorImpl<char> &result) {
}
std::error_code set_current_path(const Twine &path) {
+ sandbox::violationIfEnabled();
+
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
@@ -561,6 +565,8 @@ static bool is_local_impl(struct STATVFS &Vfs) {
}
std::error_code is_local(const Twine &Path, bool &Result) {
+ sandbox::violationIfEnabled();
+
struct STATVFS Vfs;
if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs))
return errnoAsErrorCode();
@@ -570,6 +576,8 @@ std::error_code is_local(const Twine &Path, bool &Result) {
}
std::error_code is_local(int FD, bool &Result) {
+ sandbox::violationIfEnabled();
+
struct STATVFS Vfs;
if (::FSTATVFS(FD, &Vfs))
return errnoAsErrorCode();
@@ -618,6 +626,8 @@ static int convertAccessMode(AccessMode Mode) {
}
std::error_code access(const Twine &Path, AccessMode Mode) {
+ sandbox::violationIfEnabled();
+
SmallString<128> PathStorage;
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
@@ -637,6 +647,8 @@ std::error_code access(const Twine &Path, AccessMode Mode) {
}
bool can_execute(const Twine &Path) {
+ sandbox::violationIfEnabled();
+
return !access(Path, AccessMode::Execute);
}
@@ -646,6 +658,8 @@ bool equivalent(file_status A, file_status B) {
}
std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
+ sandbox::violationIfEnabled();
+
file_status fsA, fsB;
if (std::error_code ec = status(A, fsA))
return ec;
@@ -760,6 +774,8 @@ static std::error_code fillStatus(int StatRet, const struct stat &Status,
}
std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
+ sandbox::violationIfEnabled();
+
SmallString<128> PathStorage;
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
@@ -769,6 +785,8 @@ std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
}
std::error_code status(int FD, file_status &Result) {
+ sandbox::violationIfEnabled();
+
struct stat Status;
int StatRet = ::fstat(FD, &Status);
return fillStatus(StatRet, Status, Result);
@@ -870,6 +888,8 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
uint64_t offset, std::error_code &ec)
: Size(length), Mode(mode) {
+ sandbox::violationIfEnabled();
+
(void)Mode;
ec = init(fd, offset, mode);
if (ec)
@@ -958,6 +978,8 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
}
ErrorOr<basic_file_status> directory_entry::status() const {
+ sandbox::violationIfEnabled();
+
file_status s;
if (auto EC = fs::status(Path, s, FollowSymlinks))
return EC;
@@ -1027,6 +1049,8 @@ static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
std::error_code openFile(const Twine &Name, int &ResultFD,
CreationDisposition Disp, FileAccess Access,
OpenFlags Flags, unsigned Mode) {
+ sandbox::violationIfEnabled();
+
int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
SmallString<128> Storage;
@@ -1131,6 +1155,7 @@ std::error_code openFile(const Twine &Name, int &ResultFD,
Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
FileAccess Access, OpenFlags Flags,
unsigned Mode) {
+ sandbox::violationIfEnabled();
int FD;
std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode);
@@ -1142,6 +1167,8 @@ Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
std::error_code openFileForRead(const Twine &Name, int &ResultFD,
OpenFlags Flags,
SmallVectorImpl<char> *RealPath) {
+ sandbox::violationIfEnabled();
+
std::error_code EC =
openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
if (EC)
@@ -1183,6 +1210,8 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
SmallVectorImpl<char> *RealPath) {
+ sandbox::violationIfEnabled();
+
file_t ResultFD;
std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
if (EC)
@@ -1195,6 +1224,8 @@ file_t getStdoutHandle() { return 1; }
file_t getStderrHandle() { return 2; }
Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) {
+ sandbox::violationIfEnabled();
+
#if defined(__APPLE__)
size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
#else
@@ -1217,6 +1248,8 @@ Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) {
Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
uint64_t Offset) {
+ sandbox::violationIfEnabled();
+
#if defined(__APPLE__)
size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
#else
@@ -1296,6 +1329,8 @@ std::error_code unlockFile(int FD) {
}
std::error_code closeFile(file_t &F) {
+ sandbox::violationIfEnabled();
+
file_t TmpF = F;
F = kInvalidFile;
return Process::SafelyCloseFileDescriptor(TmpF);
@@ -1343,6 +1378,8 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
bool expand_tilde) {
+ sandbox::violationIfEnabled();
+
dest.clear();
if (path.isTriviallyEmpty())
return std::error_code();
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index be007b7abdb51..f848aec030cd6 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -198,6 +198,8 @@ TimePoint<> basic_file_status::getLastModificationTime() const {
uint32_t file_status::getLinkCount() const { return NumLinks; }
std::error_code current_path(SmallVectorImpl<char> &result) {
+ sandbox::violationIfEnabled();
+
SmallVector<wchar_t, MAX_PATH> cur_path;
DWORD len = MAX_PATH;
@@ -226,6 +228,8 @@ std::error_code current_path(SmallVectorImpl<char> &result) {
}
std::error_code set_current_path(const Twine &path) {
+ sandbox::violationIfEnabled();
+
// Convert to utf-16.
SmallVector<wchar_t, 128> wide_path;
if (std::error_code ec = widenPath(path, wide_path))
@@ -350,6 +354,8 @@ static std::error_code is_local_internal(SmallVectorImpl<wchar_t> &Path,
}
std::error_code is_local(const Twine &path, bool &result) {
+ sandbox::violationIfEnabled();
+
if (!llvm::sys::fs::exists(path) || !llvm::sys::path::has_root_path(path))
return make_error_code(errc::no_such_file_or_directory);
@@ -413,6 +419,8 @@ static std::error_code realPathFromHandle(HANDLE H,
}
std::error_code is_local(int FD, bool &Result) {
+ sandbox::violationIfEnabled();
+
SmallVector<wchar_t, 128> FinalPath;
HANDLE Handle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
@@ -635,6 +643,8 @@ std::error_code resize_file_sparse(int FD, uint64_t Size) {
}
std::error_code access(const Twine &Path, AccessMode Mode) {
+ sandbox::violationIfEnabled();
+
SmallVector<wchar_t, 128> PathUtf16;
if (std::error_code EC = widenPath(Path, PathUtf16))
@@ -674,6 +684,8 @@ bool equivalent(file_status A, file_status B) {
}
std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
+ sandbox::violationIfEnabled();
+
file_status fsA, fsB;
if (std::error_code ec = status(A, fsA))
return ec;
@@ -789,6 +801,8 @@ handle_status_error:
}
std::error_code status(const Twine &path, file_status &result, bool Follow) {
+ sandbox::violationIfEnabled();
+
SmallString<128> path_storage;
SmallVector<wchar_t, 128> path_utf16;
@@ -823,11 +837,15 @@ std::error_code status(const Twine &path, file_status &result, bool Follow) {
}
std::error_code status(int FD, file_status &Result) {
+ sandbox::violationIfEnabled();
+
HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
return getStatus(FileHandle, Result);
}
std::error_code status(file_t FileHandle, file_status &Result) {
+ sandbox::violationIfEnabled();
+
return getStatus(FileHandle, Result);
}
@@ -957,6 +975,8 @@ mapped_file_region::mapped_file_region(sys::fs::file_t fd, mapmode mode,
size_t length, uint64_t offset,
std::error_code &ec)
: Size(length) {
+ sandbox::violationIfEnabled();
+
ec = init(fd, offset, mode);
if (ec)
copyFrom(mapped_file_region());
@@ -1242,6 +1262,8 @@ static std::error_code openNativeFileInternal(const Twine &Name,
Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
FileAccess Access, OpenFlags Flags,
unsigned Mode) {
+ sandbox::violationIfEnabled();
+
// Verify that we don't have both "append" and "excl".
assert((!(Disp == CD_CreateNew) || !(Flags & OF_Append)) &&
"Cannot specify both 'CreateNew' and 'Append' file creation flags!");
@@ -1277,6 +1299,8 @@ Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
std::error_code openFile(const Twine &Name, int &ResultFD,
CreationDisposition Disp, FileAccess Access,
OpenFlags Flags, unsigned int Mode) {
+ sandbox::violationIfEnabled();
+
Expected<file_t> Result = openNativeFile(Name, Disp, Access, Flags);
if (!Result)
return errorToErrorCode(Result.takeError());
@@ -1300,12 +1324,16 @@ static std::error_code directoryRealPath(const Twine &Name,
std::error_code openFileForRead(const Twine &Name, int &ResultFD,
OpenFlags Flags,
SmallVectorImpl<char> *RealPath) {
+ sandbox::violationIfEnabled();
+
Expected<HANDLE> NativeFile = openNativeFileForRead(Name, Flags, RealPath);
return nativeFileToFd(std::move(NativeFile), ResultFD, OF_None);
}
Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
SmallVectorImpl<char> *RealPath) {
+ sandbox::violationIfEnabled();
+
Expected<file_t> Result =
openNativeFile(Name, CD_OpenExisting, FA_Read, Flags);
@@ -1324,9 +1352,9 @@ file_t getStdinHandle() { return ::GetStdHandle(STD_INPUT_HANDLE); }
file_t getStdoutHandle() { return ::GetStdHandle(STD_OUTPUT_HANDLE); }
file_t getStderrHandle() { return ::GetStdHandle(STD_ERROR_HANDLE); }
-Expected<size_t> readNativeFileImpl(file_t FileHandle,
- MutableArrayRef<char> Buf,
- OVERLAPPED *Overlap) {
+static Expected<size_t> readNativeFileImpl(file_t FileHandle,
+ MutableArrayRef<char> Buf,
+ OVERLAPPED *Overlap) {
// ReadFile can only read 2GB at a time. The caller should check the number of
// bytes and read in a loop until termination.
DWORD BytesToRead =
@@ -1342,12 +1370,16 @@ Expected<size_t> readNativeFileImpl(file_t FileHandle,
}
Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf) {
+ sandbox::violationIfEnabled();
+
return readNativeFileImpl(FileHandle, Buf, /*Overlap=*/nullptr);
}
Expected<size_t> readNativeFileSlice(file_t FileHandle,
MutableArrayRef<char> Buf,
uint64_t Offset) {
+ sandbox::violationIfEnabled();
+
OVERLAPPED Overlapped = {};
Overlapped.Offset = uint32_t(Offset);
Overlapped.OffsetHigh = uint32_t(Offset >> 32);
@@ -1492,6 +1524,8 @@ void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
bool expand_tilde) {
+ sandbox::violationIfEnabled();
+
dest.clear();
if (path.isTriviallyEmpty())
return std::error_code();
>From acf2f4e1c190c0ccc82d3265052d2e5fe41cd24d Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:40:27 -0700
Subject: [PATCH 06/19] [Support] Bless `vfs::RealFileSystem` and friends in IO
sandbox
---
llvm/lib/Support/VirtualFileSystem.cpp | 33 ++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index 547e6c9abf57b..05353a23a066c 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -220,6 +220,8 @@ class RealFile : public File {
RealFile::~RealFile() { close(); }
ErrorOr<Status> RealFile::status() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
assert(FD != kInvalidFile && "cannot stat closed file");
if (!S.isStatusKnown()) {
file_status RealStatus;
@@ -237,18 +239,24 @@ ErrorOr<std::string> RealFile::getName() {
ErrorOr<std::unique_ptr<MemoryBuffer>>
RealFile::getBuffer(const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator, bool IsVolatile) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
assert(FD != kInvalidFile && "cannot get buffer for closed file");
return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
IsVolatile);
}
std::error_code RealFile::close() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
std::error_code EC = sys::fs::closeFile(FD);
FD = kInvalidFile;
return EC;
}
void RealFile::setPath(const Twine &Path) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
RealName = Path.str();
if (auto Status = status())
S = Status.get().copyWithNewName(Status.get(), Path);
@@ -328,6 +336,8 @@ class RealFileSystem : public FileSystem {
} // namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
SmallString<256> Storage;
sys::fs::file_status RealStatus;
if (std::error_code EC =
@@ -338,15 +348,21 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
ErrorOr<std::unique_ptr<File>>
RealFileSystem::openFileForRead(const Twine &Name) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
return openFileForReadWithFlags(Name, sys::fs::OF_Text);
}
ErrorOr<std::unique_ptr<File>>
RealFileSystem::openFileForReadBinary(const Twine &Name) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
return openFileForReadWithFlags(Name, sys::fs::OF_None);
}
llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
if (WD && *WD)
return std::string(WD->get().Specified);
if (WD)
@@ -359,6 +375,8 @@ llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
}
std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
if (!WD)
return llvm::sys::fs::set_current_path(Path);
@@ -376,12 +394,16 @@ std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) {
}
std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
SmallString<256> Storage;
return llvm::sys::fs::is_local(adjustPath(Path, Storage), Result);
}
std::error_code RealFileSystem::getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
SmallString<256> Storage;
return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
}
@@ -417,12 +439,17 @@ class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
llvm::sys::fs::directory_iterator Iter;
public:
- RealFSDirIter(const Twine &Path, std::error_code &EC) : Iter(Path, EC) {
- if (Iter != llvm::sys::fs::directory_iterator())
+ RealFSDirIter(const Twine &Path, std::error_code &EC) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
+ Iter = sys::fs::directory_iterator(Path, EC);
+ if (Iter != sys::fs::directory_iterator())
CurrentEntry = directory_entry(Iter->path(), Iter->type());
}
std::error_code increment() override {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
std::error_code EC;
Iter.increment(EC);
CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
@@ -436,6 +463,8 @@ class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
directory_iterator RealFileSystem::dir_begin(const Twine &Dir,
std::error_code &EC) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
SmallString<128> Storage;
return directory_iterator(
std::make_shared<RealFSDirIter>(adjustPath(Dir, Storage), EC));
>From 9588a13da463af8bf244fbc3258e0d4f6c8e0e74 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:42:35 -0700
Subject: [PATCH 07/19] [Support] Allow `LockFileManager` in IO sandbox
---
llvm/lib/Support/LockFileManager.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index cdded51108b50..22c7de3b94b1d 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/ExponentialBackoff.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
@@ -161,6 +162,8 @@ LockFileManager::LockFileManager(StringRef FileName)
: FileName(FileName), Owner(OwnerUnknown{}) {}
Expected<bool> LockFileManager::tryLock() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
assert(std::holds_alternative<OwnerUnknown>(Owner) &&
"lock has already been attempted");
@@ -246,6 +249,8 @@ Expected<bool> LockFileManager::tryLock() {
}
LockFileManager::~LockFileManager() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
if (!std::holds_alternative<OwnedByUs>(Owner))
return;
@@ -259,6 +264,8 @@ LockFileManager::~LockFileManager() {
WaitForUnlockResult
LockFileManager::waitForUnlockFor(std::chrono::seconds MaxSeconds) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
auto *LockFileOwner = std::get_if<OwnedByAnother>(&Owner);
assert(LockFileOwner &&
"waiting for lock to be unlocked without knowing the owner");
@@ -288,5 +295,7 @@ LockFileManager::waitForUnlockFor(std::chrono::seconds MaxSeconds) {
}
std::error_code LockFileManager::unsafeMaybeUnlock() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
return sys::fs::remove(LockFileName);
}
>From 9f5e5c18597d1ccea39a8b09968155688c6d9a0f Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:43:22 -0700
Subject: [PATCH 08/19] [Support] Allow `raw_fd_ostream` in IO sandbox
---
llvm/lib/Support/raw_ostream.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 07b99896543bd..e6ed38f29b83f 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -20,6 +20,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/NativeFormatting.h"
#include "llvm/Support/Process.h"
@@ -565,6 +566,9 @@ void format_object_base::home() {
static int getFD(StringRef Filename, std::error_code &EC,
sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
sys::fs::OpenFlags Flags) {
+ // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
assert((Access & sys::fs::FA_Write) &&
"Cannot make a raw_ostream from a read-only descriptor!");
@@ -617,6 +621,9 @@ raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered,
OStreamKind K)
: raw_pwrite_stream(unbuffered, K), FD(fd), ShouldClose(shouldClose) {
+ // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
if (FD < 0 ) {
ShouldClose = false;
return;
>From 81111a2dd2cdd6b9b47359ee6faa5a4291864dcc Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:46:07 -0700
Subject: [PATCH 09/19] [Support] Allow `OnDiskOutputBackend` in IO sandbox
---
llvm/lib/Support/VirtualOutputBackends.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index de59b8ab63a53..b78d54c06afa3 100644
--- a/llvm/lib/Support/VirtualOutputBackends.cpp
+++ b/llvm/lib/Support/VirtualOutputBackends.cpp
@@ -18,6 +18,7 @@
#include "llvm/Support/VirtualOutputBackends.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -255,6 +256,8 @@ static Error createDirectoriesOnDemand(StringRef OutputPath,
}
Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
// Create a temporary file.
// Insert -%%%%%%%% before the extension (if any), and because some tools
// (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
@@ -283,6 +286,8 @@ Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
}
Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
assert(OutputPath != "-" && "Unexpected request for FD of stdout");
// Disable temporary file for other non-regular files, and if we get a status
@@ -331,6 +336,8 @@ Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
}
Error OnDiskOutputFile::initializeStream() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
// Open the file stream.
if (OutputPath == "-") {
std::error_code EC;
@@ -435,6 +442,8 @@ areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination) {
}
Error OnDiskOutputFile::reset() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
// Destroy the streams to flush them.
BufferOS.reset();
if (!FileOS)
@@ -449,6 +458,8 @@ Error OnDiskOutputFile::reset() {
}
Error OnDiskOutputFile::keep() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
if (auto E = reset())
return E;
@@ -553,6 +564,8 @@ Error OnDiskOutputFile::keep() {
}
Error OnDiskOutputFile::discard() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
// Destroy the streams to flush them.
if (auto E = reset())
return E;
@@ -575,6 +588,8 @@ Error OnDiskOutputFile::discard() {
}
Error OnDiskOutputBackend::makeAbsolute(SmallVectorImpl<char> &Path) const {
+ // FIXME: Should this really call sys::fs::make_absolute?
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
return convertToOutputError(StringRef(Path.data(), Path.size()),
sys::fs::make_absolute(Path));
}
@@ -582,6 +597,8 @@ Error OnDiskOutputBackend::makeAbsolute(SmallVectorImpl<char> &Path) const {
Expected<std::unique_ptr<OutputFileImpl>>
OnDiskOutputBackend::createFileImpl(StringRef Path,
std::optional<OutputConfig> Config) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+
SmallString<256> AbsPath;
if (Path != "-") {
AbsPath = Path;
>From eea1b449ccf64149bd94af1459989018bca40520 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:50:09 -0700
Subject: [PATCH 10/19] [clang] Allow `ModuleCache` and `GlobalModuleIndex` in
IO sandbox
---
clang/lib/Serialization/GlobalModuleIndex.cpp | 7 +++++++
clang/lib/Serialization/ModuleCache.cpp | 19 +++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 1e2272c48bd04..297f5645b1645 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -24,6 +24,7 @@
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
@@ -250,6 +251,9 @@ GlobalModuleIndex::~GlobalModuleIndex() {
std::pair<GlobalModuleIndex *, llvm::Error>
GlobalModuleIndex::readIndex(StringRef Path) {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
// Load the index file, if it's there.
llvm::SmallString<128> IndexPath;
IndexPath += Path;
@@ -843,6 +847,9 @@ llvm::Error
GlobalModuleIndex::writeIndex(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
StringRef Path) {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
llvm::SmallString<128> IndexPath;
IndexPath += Path;
llvm::sys::path::append(IndexPath, IndexFileName);
diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp
index 9850956380423..fbe169db4accd 100644
--- a/clang/lib/Serialization/ModuleCache.cpp
+++ b/clang/lib/Serialization/ModuleCache.cpp
@@ -11,6 +11,7 @@
#include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleFile.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/LockFileManager.h"
#include "llvm/Support/Path.h"
@@ -27,6 +28,9 @@ void clang::maybePruneImpl(StringRef Path, time_t PruneInterval,
if (PruneInterval <= 0 || PruneAfter <= 0)
return;
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
llvm::SmallString<128> TimestampFile(Path);
llvm::sys::path::append(TimestampFile, "modules.timestamp");
@@ -103,6 +107,9 @@ class CrossProcessModuleCache : public ModuleCache {
public:
void prepareForGetLock(StringRef ModuleFilename) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
// FIXME: Do this in LockFileManager and only if the directory doesn't
// exist.
StringRef Dir = llvm::sys::path::parent_path(ModuleFilename);
@@ -111,10 +118,16 @@ class CrossProcessModuleCache : public ModuleCache {
std::unique_ptr<llvm::AdvisoryLock>
getLock(StringRef ModuleFilename) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
return std::make_unique<llvm::LockFileManager>(ModuleFilename);
}
std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
std::string TimestampFilename =
serialization::ModuleFile::getTimestampFilename(ModuleFilename);
llvm::sys::fs::file_status Status;
@@ -124,6 +137,9 @@ class CrossProcessModuleCache : public ModuleCache {
}
void updateModuleTimestamp(StringRef ModuleFilename) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
// Overwrite the timestamp file contents so that file's mtime changes.
std::error_code EC;
llvm::raw_fd_ostream OS(
@@ -138,6 +154,9 @@ class CrossProcessModuleCache : public ModuleCache {
void maybePrune(StringRef Path, time_t PruneInterval,
time_t PruneAfter) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
maybePruneImpl(Path, PruneInterval, PruneAfter);
}
>From e1aeec7e5c2b74f0a2bb3599abc1b4bb31861d3f Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:50:33 -0700
Subject: [PATCH 11/19] [clang] Allow `HTMLDiagnostics` in IO sandbox
---
clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 217b853305ed1..b201b644359e9 100644
--- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -37,6 +37,7 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -257,6 +258,9 @@ void HTMLDiagnostics::FlushDiagnosticsImpl(
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
FilesMade *filesMade) {
+ // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
>From 48414bb98b370a1e0855a709498f1c864085ebd1 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:50:47 -0700
Subject: [PATCH 12/19] [clang] Allow ThinLTO indexing in IO sandbox
---
clang/lib/CodeGen/BackendUtil.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index aefc262dca17f..e99e54f50d604 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -46,6 +46,7 @@
#include "llvm/Support/BuryPointer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Program.h"
@@ -1434,6 +1435,8 @@ void clang::emitBackendOutput(CompilerInstance &CI, CodeGenOptions &CGOpts,
std::unique_ptr<llvm::Module> EmptyModule;
if (!CGOpts.ThinLTOIndexFile.empty()) {
+ // FIXME(sandboxing): Figure out how to support distributed indexing.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
// If we are performing a ThinLTO importing compile, load the function index
// into memory and pass it into runThinLTOBackend, which will run the
// function importer and invoke LTO passes.
>From dc64a2baa2256e26ebae2ae8151c8f2bd6d54002 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 16:51:03 -0700
Subject: [PATCH 13/19] [clang] Allow crash diagnostic file in IO sandbox
---
clang/lib/Driver/Driver.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 40ea513e85427..ede5fb0e94423 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -87,6 +87,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -1870,6 +1871,8 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
using namespace llvm::sys;
assert(llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin() &&
"Only knows about .crash files on Darwin");
+ // This is not a formal output of the compiler, let's bypass the sandbox.
+ [[maybe_unused]] auto BypassSandbox = sandbox::scopedDisable();
// The .crash file can be found on at ~/Library/Logs/DiagnosticReports/
// (or /Library/Logs/DiagnosticReports for root) and has the filename pattern
>From 39ab9d5c1f17a9a0117d64a7c63db7d656236b34 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 19:55:02 -0700
Subject: [PATCH 14/19] [llvm] Allow `AsmPrinter` in IO sandbox
---
llvm/include/llvm/CodeGen/AsmPrinter.h | 8 --------
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 1 -
llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 6 +++++-
3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 9ace2555b4b62..19ca44429af4d 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -16,7 +16,6 @@
#define LLVM_CODEGEN_ASMPRINTER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -88,10 +87,6 @@ namespace remarks {
class RemarkStreamer;
}
-namespace vfs {
-class FileSystem;
-}
-
/// This class is intended to be used as a driving class for all asm writers.
class LLVM_ABI AsmPrinter : public MachineFunctionPass {
public:
@@ -110,9 +105,6 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// generating (such as the current section etc).
std::unique_ptr<MCStreamer> OutStreamer;
- /// The VFS to resolve asm include directives.
- IntrusiveRefCntPtr<vfs::FileSystem> VFS;
-
/// The current machine function.
MachineFunction *MF = nullptr;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 8aa488f0efd8f..ceba3833c7dd2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -482,7 +482,6 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
}
bool AsmPrinter::doInitialization(Module &M) {
- VFS = vfs::getRealFileSystem();
auto *MMIWP = getAnalysisIfAvailable<MachineModuleInfoWrapperPass>();
MMI = MMIWP ? &MMIWP->getMMI() : nullptr;
HasSplitStack = false;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 8dd8b9da9c50c..4d01e397af5c0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -99,7 +99,11 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
SourceMgr &SrcMgr = *MMI->getContext().getInlineSourceManager();
SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
- SrcMgr.setVirtualFileSystem(VFS);
+ SrcMgr.setVirtualFileSystem([] {
+ // FIXME(sandboxing): Propagating vfs::FileSystem here is lots of work.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+ return vfs::getRealFileSystem();
+ }());
std::unique_ptr<MCAsmParser> Parser(
createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
>From 1f7011925264fbf2d4d7d2bc8d0f77a71ac3e216 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 19:55:17 -0700
Subject: [PATCH 15/19] [llvm] Allow `BTFDebug` in IO sandbox
---
llvm/lib/Target/BPF/BTFDebug.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index a652b7e9c537f..71cfdf1e98438 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -25,6 +25,7 @@
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/IOSandbox.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -1108,12 +1109,17 @@ std::string BTFDebug::populateFileContent(const DIFile *File) {
std::string Line;
Content.push_back(Line); // Line 0 for empty string
+ auto LoadFile = [](StringRef FileName) {
+ // FIXME(sandboxing): Propagating vfs::FileSystem here is lots of work.
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
+ return MemoryBuffer::getFile(FileName);
+ };
+
std::unique_ptr<MemoryBuffer> Buf;
auto Source = File->getSource();
if (Source)
Buf = MemoryBuffer::getMemBufferCopy(*Source);
- else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
- MemoryBuffer::getFile(FileName))
+ else if (ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = LoadFile(FileName))
Buf = std::move(*BufOrErr);
if (Buf)
for (line_iterator I(*Buf, false), E; I != E; ++I)
>From 96e703d63274a228a991b8a347f9441cc4be00a3 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 19:55:47 -0700
Subject: [PATCH 16/19] [clang] Allow `FileManager` to read stdin
---
clang/lib/Basic/FileManager.cpp | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index e744cc0afcded..f1fc453be898a 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -347,12 +347,15 @@ llvm::Expected<FileEntryRef> FileManager::getSTDIN() {
if (STDIN)
return *STDIN;
- std::unique_ptr<llvm::MemoryBuffer> Content;
- if (auto ContentOrError = llvm::MemoryBuffer::getSTDIN())
- Content = std::move(*ContentOrError);
- else
+ auto ContentOrError = [] {
+ [[maybe_unused]] auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
+ return llvm::MemoryBuffer::getSTDIN();
+ }();
+
+ if (!ContentOrError)
return llvm::errorCodeToError(ContentOrError.getError());
+ auto Content = std::move(*ContentOrError);
STDIN = getVirtualFileRef(Content->getBufferIdentifier(),
Content->getBufferSize(), 0);
FileEntry &FE = const_cast<FileEntry &>(STDIN->getFileEntry());
>From f96829ebf211c6ef0cbd9f10f20a6082fa30935b Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Mon, 27 Oct 2025 19:56:22 -0700
Subject: [PATCH 17/19] [clang] Use the VFS to make prebuilt module paths
absolute
---
clang/lib/Lex/HeaderSearch.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 65c324c10ca5d..02b34b10375a3 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -221,7 +221,7 @@ std::string HeaderSearch::getPrebuiltModuleFileName(StringRef ModuleName,
// file.
for (const std::string &Dir : HSOpts.PrebuiltModulePaths) {
SmallString<256> Result(Dir);
- llvm::sys::fs::make_absolute(Result);
+ FileMgr.makeAbsolutePath(Result);
if (ModuleName.contains(':'))
// The separator of C++20 modules partitions (':') is not good for file
// systems, here clang and gcc choose '-' by default since it is not a
>From d4a425a0dae4036bf6a2aa5033bef46b28036e36 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 28 Oct 2025 06:56:00 -0700
Subject: [PATCH 18/19] Squash with "[clang] Enable IO sandboxing in -cc1 and
-cc1as"
---
llvm/lib/Support/Unix/Signals.inc | 1 +
llvm/lib/Support/Windows/Signals.inc | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 78d6540db98a7..3b73897777402 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -354,6 +354,7 @@ void sys::unregisterHandlers() {
/// Process the FilesToRemove list.
static void RemoveFilesToRemove() {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
FileToRemoveList::removeAllFiles(FilesToRemove);
}
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index 648d6a50287ec..c75bb966e0957 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -563,11 +563,13 @@ static void Cleanup(bool ExecuteSignalHandlers) {
CleanupExecuted = true;
// FIXME: open files cannot be deleted.
- if (FilesToRemove != NULL)
+ if (FilesToRemove != NULL) {
+ [[maybe_unused]] auto BypassSandbox = sys::sandbox::scopedDisable();
while (!FilesToRemove->empty()) {
llvm::sys::fs::remove(FilesToRemove->back());
FilesToRemove->pop_back();
}
+ }
if (ExecuteSignalHandlers)
llvm::sys::RunSignalHandlers();
>From fbb67e6e7c83ae735d97b0122fdba17be2da4ceb Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 30 Oct 2025 15:53:00 -0700
Subject: [PATCH 19/19] Windows CI fix?
---
llvm/lib/Support/Unix/Signals.inc | 2 ++
llvm/lib/Support/Windows/Signals.inc | 2 ++
2 files changed, 4 insertions(+)
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 3b73897777402..770fd701c1b9f 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -359,6 +359,8 @@ static void RemoveFilesToRemove() {
}
void sys::CleanupOnSignal(uintptr_t Context) {
+ [[maybe_unused]] auto BypassSandbox = sandbox::scopedDisable();
+
int Sig = (int)Context;
if (llvm::is_contained(InfoSigs, Sig)) {
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index c75bb966e0957..9910f9dd9c86d 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -778,6 +778,8 @@ WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) {
}
void sys::CleanupOnSignal(uintptr_t Context) {
+ [[maybe_unused]] auto BypassSandbox = sandbox::scopedDisable();
+
LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context;
// Broken pipe is not a crash.
//
More information about the llvm-commits
mailing list