[clang] [llvm] [llvm][clang] Sandbox filesystem reads (PR #162151)
Jan Svoboda via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 6 13:27:47 PDT 2025
https://github.com/jansvoboda11 created https://github.com/llvm/llvm-project/pull/162151
This PR introduces a new mechanism for enforcing a sandbox of filesystem reads from the compiler. A fatal error is raised whenever the `llvm::sys::fs` APIs get used directly instead of going through the blessed virtual interface of `llvm::vfs::FileSystem`.
>From f5952bd528dc90c8b106037e1be78cbf735d386c Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Wed, 16 Jul 2025 11:24:41 -0700
Subject: [PATCH 01/11] [llvm][clang] Sandbox IO operations (infrastructure)
---
clang/lib/Driver/Job.cpp | 5 ++++
llvm/include/llvm/Support/IOSandbox.h | 20 +++++++++++++++
llvm/lib/Support/IOSandbox.cpp | 19 ++++++++++++++
llvm/lib/Support/IOSandboxInternal.h | 36 +++++++++++++++++++++++++++
llvm/lib/Support/Signals.cpp | 4 +++
5 files changed, 84 insertions(+)
create mode 100644 llvm/include/llvm/Support/IOSandbox.h
create mode 100644 llvm/lib/Support/IOSandbox.cpp
create mode 100644 llvm/lib/Support/IOSandboxInternal.h
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 880e9e396c41e..4f44864bef1ac 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"
@@ -425,6 +426,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.
+ auto EnableSandbox = llvm::sys::sandbox_scoped_enable();
+
llvm::CrashRecoveryContext CRC;
CRC.DumpStackAndCleanupOnFailure = true;
diff --git a/llvm/include/llvm/Support/IOSandbox.h b/llvm/include/llvm/Support/IOSandbox.h
new file mode 100644
index 0000000000000..1a8fb9788e3f6
--- /dev/null
+++ b/llvm/include/llvm/Support/IOSandbox.h
@@ -0,0 +1,20 @@
+//===- 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
+
+#include "llvm/Support/SaveAndRestore.h"
+
+namespace llvm::sys {
+SaveAndRestore<bool> sandbox_scoped_enable();
+SaveAndRestore<bool> sandbox_scoped_disable();
+void sandbox_violation_if_enabled();
+} // namespace llvm::sys
+
+#endif
diff --git a/llvm/lib/Support/IOSandbox.cpp b/llvm/lib/Support/IOSandbox.cpp
new file mode 100644
index 0000000000000..a046d38b48fc3
--- /dev/null
+++ b/llvm/lib/Support/IOSandbox.cpp
@@ -0,0 +1,19 @@
+#include "llvm/Support/IOSandbox.h"
+
+#include <cassert>
+
+using namespace llvm;
+
+thread_local bool IOSandboxEnabled = false;
+
+SaveAndRestore<bool> sys::sandbox_scoped_enable() {
+ return {IOSandboxEnabled, true};
+}
+
+SaveAndRestore<bool> sys::sandbox_scoped_disable() {
+ return {IOSandboxEnabled, false};
+}
+
+void sys::sandbox_violation_if_enabled() {
+ assert(!IOSandboxEnabled && "sandbox violation");
+}
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
new file mode 100644
index 0000000000000..184b220417fff
--- /dev/null
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -0,0 +1,36 @@
+#ifndef LLVM_SUPPORT_IOSANDBOXINTERNAL_H
+#define LLVM_SUPPORT_IOSANDBOXINTERNAL_H
+
+#include "llvm/Support/IOSandbox.h"
+
+namespace llvm {
+namespace detail {
+template <class FnTy> struct Interposed;
+
+template <class RetTy, class... ArgTy> struct Interposed<RetTy (*)(ArgTy...)> {
+ RetTy (*Fn)(ArgTy...);
+
+ RetTy operator()(ArgTy... Arg) const {
+ sys::sandbox_violation_if_enabled();
+ return Fn(std::forward<ArgTy>(Arg)...);
+ }
+};
+
+template <class RetTy, class... ArgTy>
+struct Interposed<RetTy (*)(ArgTy..., ...)> {
+ RetTy (*Fn)(ArgTy..., ...);
+
+ template <class... CVarArgTy>
+ RetTy operator()(ArgTy... Arg, CVarArgTy... CVarArg) const {
+ sys::sandbox_violation_if_enabled();
+ return Fn(std::forward<ArgTy>(Arg)..., std::forward<CVarArgTy>(CVarArg)...);
+ }
+};
+
+template <class FnTy> constexpr auto interpose(FnTy Fn) {
+ return Interposed<FnTy>{Fn};
+}
+} // namespace detail
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp
index f8a14a45ddc3e..076ec293750af 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.
+ auto BypassSandbox = sandbox_scoped_disable();
+
for (CallbackAndCookie &RunMe : CallBacksToRun()) {
auto Expected = CallbackAndCookie::Status::Initialized;
auto Desired = CallbackAndCookie::Status::Executing;
>From 58d44c7e35ff562f20cc1d02300f7f65fc1cc167 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Wed, 16 Jul 2025 11:20:25 -0700
Subject: [PATCH 02/11] [llvm][clang] Sandbox IO operations (getting
`vfs::RealFileSystem`)
---
clang/lib/CodeGen/BackendUtil.cpp | 3 +++
clang/tools/driver/cc1_main.cpp | 7 ++++++-
clang/tools/driver/cc1as_main.cpp | 6 +++++-
llvm/lib/Support/VirtualFileSystem.cpp | 3 +++
4 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 64f1917739e12..a4a238ecc5c75 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"
@@ -1412,6 +1413,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.
+ auto BypassSandbox = sys::sandbox_scoped_disable();
// 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.
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 49f8843515a35..f8588d0ac4549 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 = [] {
+ auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ return llvm::vfs::getRealFileSystem();
+ }();
+ Clang->createVirtualFileSystem(std::move(VFS), DiagsBuffer);
// Create the actual diagnostics engine.
Clang->createDiagnostics();
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index ef79e45364a2f..b2dc92fa5159d 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"
@@ -669,7 +670,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 = [] {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+ return vfs::getRealFileSystem();
+ }();
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index c754b30d8de4a..1d27d02a27f47 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,12 @@ void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type,
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
static IntrusiveRefCntPtr<FileSystem> FS =
makeIntrusiveRefCnt<RealFileSystem>(true);
+ sys::sandbox_violation_if_enabled();
return FS;
}
std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
+ sys::sandbox_violation_if_enabled();
return std::make_unique<RealFileSystem>(false);
}
>From fad5e43e69b68776945b0367f454139ecd9efdf6 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 10 Jul 2025 08:01:31 -0700
Subject: [PATCH 03/11] [llvm][clang] Sandbox IO operations (read, pread)
---
clang/lib/Serialization/GlobalModuleIndex.cpp | 4 ++
clang/tools/driver/cc1_main.cpp | 20 +++---
clang/tools/driver/cc1as_main.cpp | 7 +-
llvm/lib/Support/IOSandboxInternal.h | 10 +++
llvm/lib/Support/Unix/Path.inc | 68 ++++++++++---------
llvm/lib/Support/VirtualFileSystem.cpp | 11 ++-
6 files changed, 76 insertions(+), 44 deletions(-)
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 1e2272c48bd04..613121a9596fd 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.
+ auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+
// Load the index file, if it's there.
llvm::SmallString<128> IndexPath;
IndexPath += Path;
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index f8588d0ac4549..af30ba68dfde4 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -307,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.
+ auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ 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()) {
// It is possible that the compiler instance doesn't own a file manager here
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index b2dc92fa5159d..5e1699f96cb36 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -425,8 +425,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.
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+ return MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
+ }();
if (std::error_code EC = Buffer.getError()) {
return Diags.Report(diag::err_fe_error_reading)
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 184b220417fff..72845966d5eb3 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -3,6 +3,13 @@
#include "llvm/Support/IOSandbox.h"
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+extern thread_local bool IOSandboxEnabled;
+
namespace llvm {
namespace detail {
template <class FnTy> struct Interposed;
@@ -31,6 +38,9 @@ template <class FnTy> constexpr auto interpose(FnTy Fn) {
return Interposed<FnTy>{Fn};
}
} // namespace detail
+
+static constexpr auto read = detail::interpose(::read);
+static constexpr auto pread = detail::interpose(::pread);
} // namespace llvm
#endif
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 0d991ead72416..fa27f86241b7d 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -114,6 +114,8 @@ typedef uint_t uint;
#define STATVFS_F_FLAG(vfs) (vfs).f_flags
#endif
+#include "IOSandboxInternal.h"
+
using namespace llvm;
namespace llvm {
@@ -197,7 +199,7 @@ std::string getMainExecutable(const char *argv0, void *MainAddr) {
uint32_t size = sizeof(exe_path);
if (_NSGetExecutablePath(exe_path, &size) == 0) {
char link_path[PATH_MAX];
- if (realpath(exe_path, link_path))
+ if (::realpath(exe_path, link_path))
return link_path;
}
#elif defined(__FreeBSD__)
@@ -368,7 +370,7 @@ ErrorOr<space_info> disk_space(const Twine &Path) {
std::error_code current_path(SmallVectorImpl<char> &result) {
result.clear();
- const char *pwd = ::getenv("PWD");
+ const char *pwd = getenv("PWD");
llvm::sys::fs::file_status PWDStatus, DotStatus;
if (pwd && llvm::sys::path::is_absolute(pwd) &&
!llvm::sys::fs::status(pwd, PWDStatus) &&
@@ -381,7 +383,7 @@ std::error_code current_path(SmallVectorImpl<char> &result) {
result.resize_for_overwrite(PATH_MAX);
while (true) {
- if (::getcwd(result.data(), result.size()) == nullptr) {
+ if (getcwd(result.data(), result.size()) == nullptr) {
// See if there was a real error.
if (errno != ENOMEM) {
result.clear();
@@ -402,7 +404,7 @@ std::error_code set_current_path(const Twine &path) {
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
- if (::chdir(p.begin()) == -1)
+ if (chdir(p.begin()) == -1)
return errnoAsErrorCode();
return std::error_code();
@@ -413,7 +415,7 @@ std::error_code create_directory(const Twine &path, bool IgnoreExisting,
SmallString<128> path_storage;
StringRef p = path.toNullTerminatedStringRef(path_storage);
- if (::mkdir(p.begin(), Perms) == -1) {
+ if (mkdir(p.begin(), Perms) == -1) {
if (errno != EEXIST || !IgnoreExisting)
return errnoAsErrorCode();
}
@@ -430,7 +432,7 @@ std::error_code create_link(const Twine &to, const Twine &from) {
StringRef f = from.toNullTerminatedStringRef(from_storage);
StringRef t = to.toNullTerminatedStringRef(to_storage);
- if (::symlink(t.begin(), f.begin()) == -1)
+ if (symlink(t.begin(), f.begin()) == -1)
return errnoAsErrorCode();
return std::error_code();
@@ -443,7 +445,7 @@ std::error_code create_hard_link(const Twine &to, const Twine &from) {
StringRef f = from.toNullTerminatedStringRef(from_storage);
StringRef t = to.toNullTerminatedStringRef(to_storage);
- if (::link(t.begin(), f.begin()) == -1)
+ if (link(t.begin(), f.begin()) == -1)
return errnoAsErrorCode();
return std::error_code();
@@ -594,7 +596,7 @@ std::error_code rename(const Twine &from, const Twine &to) {
std::error_code resize_file(int FD, uint64_t Size) {
// Use ftruncate as a fallback. It may or may not allocate space. At least on
// OS X with HFS+ it does.
- if (::ftruncate(FD, Size) == -1)
+ if (ftruncate(FD, Size) == -1)
return errnoAsErrorCode();
return std::error_code();
@@ -764,13 +766,13 @@ std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
struct stat Status;
- int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status);
+ int StatRet = (Follow ? stat : lstat)(P.begin(), &Status);
return fillStatus(StatRet, Status, Result);
}
std::error_code status(int FD, file_status &Result) {
struct stat Status;
- int StatRet = ::fstat(FD, &Status);
+ int StatRet = fstat(FD, &Status);
return fillStatus(StatRet, Status, Result);
}
@@ -786,13 +788,13 @@ std::error_code setPermissions(const Twine &Path, perms Permissions) {
SmallString<128> PathStorage;
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
- if (::chmod(P.begin(), Permissions))
+ if (chmod(P.begin(), Permissions))
return errnoAsErrorCode();
return std::error_code();
}
std::error_code setPermissions(int FD, perms Permissions) {
- if (::fchmod(FD, Permissions))
+ if (fchmod(FD, Permissions))
return errnoAsErrorCode();
return std::error_code();
}
@@ -803,7 +805,7 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
timespec Times[2];
Times[0] = sys::toTimeSpec(AccessTime);
Times[1] = sys::toTimeSpec(ModificationTime);
- if (::futimens(FD, Times))
+ if (futimens(FD, Times))
return errnoAsErrorCode();
return std::error_code();
#elif defined(HAVE_FUTIMES)
@@ -813,7 +815,7 @@ std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
Times[1] =
sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>(
ModificationTime));
- if (::futimes(FD, Times))
+ if (futimes(FD, Times))
return errnoAsErrorCode();
return std::error_code();
#elif defined(__MVS__)
@@ -861,7 +863,7 @@ std::error_code mapped_file_region::init(int FD, uint64_t Offset,
}
#endif // #if defined (__APPLE__)
- Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
+ Mapping = mmap(nullptr, Size, prot, flags, FD, Offset);
if (Mapping == MAP_FAILED)
return errnoAsErrorCode();
return std::error_code();
@@ -878,7 +880,7 @@ mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
void mapped_file_region::unmapImpl() {
if (Mapping)
- ::munmap(Mapping, Size);
+ munmap(Mapping, Size);
}
std::error_code mapped_file_region::sync() const {
@@ -906,7 +908,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
StringRef path,
bool follow_symlinks) {
SmallString<128> path_null(path);
- DIR *directory = ::opendir(path_null.c_str());
+ DIR *directory = opendir(path_null.c_str());
if (!directory)
return errnoAsErrorCode();
@@ -919,7 +921,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
if (it.IterationHandle)
- ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
+ closedir(reinterpret_cast<DIR *>(it.IterationHandle));
it.IterationHandle = 0;
it.CurrentEntry = directory_entry();
return std::error_code();
@@ -941,7 +943,7 @@ static file_type direntType(dirent *Entry) {
std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
errno = 0;
- dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle));
+ dirent *CurDir = readdir(reinterpret_cast<DIR *>(It.IterationHandle));
if (CurDir == nullptr && errno != 0) {
return errnoAsErrorCode();
} else if (CurDir != nullptr) {
@@ -976,7 +978,7 @@ ErrorOr<basic_file_status> directory_entry::status() const {
static bool hasProcSelfFD() {
// If we have a /proc filesystem mounted, we can quickly establish the
// real name of the file with readlink
- static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
+ static const bool Result = (access("/proc/self/fd", R_OK) == 0);
return Result;
}
#endif
@@ -1031,9 +1033,9 @@ std::error_code openFile(const Twine &Name, int &ResultFD,
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
- // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal
+ // Call open in a lambda to avoid overload resolution in RetryAfterSignal
// when open is overloaded, such as in Bionic.
- auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); };
+ auto Open = [&]() { return open(P.begin(), OpenFlags, Mode); };
if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0)
return errnoAsErrorCode();
#ifndef O_CLOEXEC
@@ -1155,7 +1157,7 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
// When F_GETPATH is availble, it is the quickest way to get
// the real path name.
char Buffer[PATH_MAX];
- if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
+ if (fcntl(ResultFD, F_GETPATH, Buffer) != -1)
RealPath->append(Buffer, Buffer + strlen(Buffer));
#else
char Buffer[PATH_MAX];
@@ -1163,7 +1165,7 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
if (hasProcSelfFD()) {
char ProcPath[64];
snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
- ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
+ ssize_t CharCount = readlink(ProcPath, Buffer, sizeof(Buffer));
if (CharCount > 0)
RealPath->append(Buffer, Buffer + CharCount);
} else {
@@ -1171,8 +1173,8 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
- // Use ::realpath to get the real path name
- if (::realpath(P.begin(), Buffer) != nullptr)
+ // Use realpath to get the real path name
+ if (realpath(P.begin(), Buffer) != nullptr)
RealPath->append(Buffer, Buffer + strlen(Buffer));
#if defined(TRY_PROC_SELF_FD)
}
@@ -1224,11 +1226,11 @@ Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf,
#endif
#ifdef HAVE_PREAD
ssize_t NumRead =
- sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Size, Offset);
+ sys::RetryAfterSignal(-1, pread, FD, Buf.data(), Size, Offset);
#else
if (lseek(FD, Offset, SEEK_SET) == -1)
return errorCodeToError(errnoAsErrorCode());
- ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
+ ssize_t NumRead = sys::RetryAfterSignal(-1, read, FD, Buf.data(), Size);
#endif
if (NumRead == -1)
return errorCodeToError(errnoAsErrorCode());
@@ -1253,7 +1255,7 @@ std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout,
Lock.l_whence = SEEK_SET;
Lock.l_start = 0;
Lock.l_len = 0;
- if (::fcntl(FD, F_SETLK, &Lock) != -1)
+ if (fcntl(FD, F_SETLK, &Lock) != -1)
return std::error_code();
int Error = errno;
if (Error != EACCES && Error != EAGAIN)
@@ -1279,7 +1281,7 @@ std::error_code lockFile(int FD, LockKind Kind) {
Lock.l_whence = SEEK_SET;
Lock.l_start = 0;
Lock.l_len = 0;
- if (::fcntl(FD, F_SETLKW, &Lock) != -1)
+ if (fcntl(FD, F_SETLKW, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
}
@@ -1290,7 +1292,7 @@ std::error_code unlockFile(int FD) {
Lock.l_whence = SEEK_SET;
Lock.l_start = 0;
Lock.l_len = 0;
- if (::fcntl(FD, F_SETLK, &Lock) != -1)
+ if (fcntl(FD, F_SETLK, &Lock) != -1)
return std::error_code();
return errnoAsErrorCode();
}
@@ -1357,14 +1359,14 @@ std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
SmallString<128> Storage;
StringRef P = path.toNullTerminatedStringRef(Storage);
char Buffer[PATH_MAX];
- if (::realpath(P.begin(), Buffer) == nullptr)
+ if (realpath(P.begin(), Buffer) == nullptr)
return errnoAsErrorCode();
dest.append(Buffer, Buffer + strlen(Buffer));
return std::error_code();
}
std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) {
- auto FChown = [&]() { return ::fchown(FD, Owner, Group); };
+ auto FChown = [&]() { return fchown(FD, Owner, Group); };
// Retry if fchown call fails due to interruption.
if ((sys::RetryAfterSignal(-1, FChown)) < 0)
return errnoAsErrorCode();
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index 1d27d02a27f47..ecd50a8004f70 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -222,6 +222,7 @@ RealFile::~RealFile() { close(); }
ErrorOr<Status> RealFile::status() {
assert(FD != kInvalidFile && "cannot stat closed file");
if (!S.isStatusKnown()) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
file_status RealStatus;
if (std::error_code EC = sys::fs::status(FD, RealStatus))
return EC;
@@ -238,6 +239,7 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
RealFile::getBuffer(const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator, bool IsVolatile) {
assert(FD != kInvalidFile && "cannot get buffer for closed file");
+ auto BypassSandbox = sys::sandbox_scoped_disable();
return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
IsVolatile);
}
@@ -307,6 +309,7 @@ class RealFileSystem : public FileSystem {
ErrorOr<std::unique_ptr<File>>
openFileForReadWithFlags(const Twine &Name, sys::fs::OpenFlags Flags) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
SmallString<256> RealName, Storage;
Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead(
adjustPath(Name, Storage), Flags, &RealName);
@@ -328,6 +331,7 @@ class RealFileSystem : public FileSystem {
} // namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
SmallString<256> Storage;
sys::fs::file_status RealStatus;
if (std::error_code EC =
@@ -352,6 +356,7 @@ llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
if (WD)
return WD->getError();
+ auto BypassSandbox = sys::sandbox_scoped_disable();
SmallString<128> Dir;
if (std::error_code EC = llvm::sys::fs::current_path(Dir))
return EC;
@@ -382,6 +387,7 @@ std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
std::error_code RealFileSystem::getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
SmallString<256> Storage;
return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
}
@@ -415,12 +421,15 @@ 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) {
+ RealFSDirIter(const Twine &Path, std::error_code &EC) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+ Iter = llvm::sys::fs::directory_iterator{Path, EC};
if (Iter != llvm::sys::fs::directory_iterator())
CurrentEntry = directory_entry(Iter->path(), Iter->type());
}
std::error_code increment() override {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
std::error_code EC;
Iter.increment(EC);
CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
>From 7d5f811bb37a859983f0fe891990ad60b1f1e346 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 10 Jul 2025 14:11:14 -0700
Subject: [PATCH 04/11] [llvm][clang] Sandbox IO operations (mmap)
---
clang/lib/Driver/Driver.cpp | 3 +++
llvm/lib/Support/IOSandboxInternal.h | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 85a1335785542..c75a46dc906d8 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.
+ auto BypassSandbox = sandbox_scoped_disable();
// The .crash file can be found on at ~/Library/Logs/DiagnosticReports/
// (or /Library/Logs/DiagnosticReports for root) and has the filename pattern
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 72845966d5eb3..f784ef7131403 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -7,6 +7,9 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
extern thread_local bool IOSandboxEnabled;
@@ -41,6 +44,7 @@ template <class FnTy> constexpr auto interpose(FnTy Fn) {
static constexpr auto read = detail::interpose(::read);
static constexpr auto pread = detail::interpose(::pread);
+static constexpr auto mmap = detail::interpose(::mmap);
} // namespace llvm
#endif
>From 08a401e431773243739302fb6f9b83c20672fc28 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 10 Jul 2025 14:31:20 -0700
Subject: [PATCH 05/11] [llvm][clang] Sandbox IO operations (readdir)
---
clang/lib/Serialization/GlobalModuleIndex.cpp | 3 +++
clang/lib/Serialization/ModuleCache.cpp | 4 ++++
llvm/lib/Support/IOSandboxInternal.h | 2 ++
3 files changed, 9 insertions(+)
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 613121a9596fd..99d90054cb09f 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -847,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.
+ auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+
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 96687277ebafd..8fd8f60878644 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.
+ auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+
llvm::SmallString<128> TimestampFile(Path);
llvm::sys::path::append(TimestampFile, "modules.timestamp");
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index f784ef7131403..163c0cfc9dad8 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -10,6 +10,7 @@
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
+#include <dirent.h>
extern thread_local bool IOSandboxEnabled;
@@ -45,6 +46,7 @@ template <class FnTy> constexpr auto interpose(FnTy Fn) {
static constexpr auto read = detail::interpose(::read);
static constexpr auto pread = detail::interpose(::pread);
static constexpr auto mmap = detail::interpose(::mmap);
+static constexpr auto readdir = detail::interpose(::readdir);
} // namespace llvm
#endif
>From 57c88631d041d720dff0b20602fedaf85c28ed69 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Thu, 10 Jul 2025 15:46:01 -0700
Subject: [PATCH 06/11] [llvm][clang] Sandbox IO operations (stat, lstat,
fstat)
---
clang/lib/Serialization/ModuleCache.cpp | 2 ++
clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 4 ++++
llvm/lib/Support/IOSandboxInternal.h | 4 ++++
llvm/lib/Support/LockFileManager.cpp | 5 +++++
llvm/lib/Support/VirtualOutputBackends.cpp | 5 +++++
llvm/lib/Support/raw_ostream.cpp | 4 ++++
6 files changed, 24 insertions(+)
diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp
index 8fd8f60878644..021068c806ca6 100644
--- a/clang/lib/Serialization/ModuleCache.cpp
+++ b/clang/lib/Serialization/ModuleCache.cpp
@@ -119,6 +119,8 @@ class CrossProcessModuleCache : public ModuleCache {
}
std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
+ // This is a compiler-internal input/output, let's bypass the sandbox.
+ auto SandboxBypass = llvm::sys::sandbox_scoped_disable();
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{})
return 0;
diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 217b853305ed1..11e53a5132563 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`.
+ auto SandboxBypass = llvm::sys::sandbox_scoped_disable();
+
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 163c0cfc9dad8..044b7dd9bd781 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -4,6 +4,7 @@
#include "llvm/Support/IOSandbox.h"
#include <stdio.h>
+#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -47,6 +48,9 @@ static constexpr auto read = detail::interpose(::read);
static constexpr auto pread = detail::interpose(::pread);
static constexpr auto mmap = detail::interpose(::mmap);
static constexpr auto readdir = detail::interpose(::readdir);
+static constexpr auto stat = detail::interpose(::stat);
+static constexpr auto lstat = detail::interpose(::lstat);
+static constexpr auto fstat = detail::interpose(::fstat);
} // namespace llvm
#endif
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index cdded51108b50..54c42e4dd53e6 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"
@@ -51,6 +52,8 @@ using namespace llvm;
/// \returns The process ID of the process that owns this lock file
std::optional<LockFileManager::OwnedByAnother>
LockFileManager::readLockFile(StringRef LockFileName) {
+ auto SandboxBypass = sys::sandbox_scoped_disable();
+
// Read the owning host and PID out of the lock file. If it appears that the
// owning process is dead, the lock file is invalid.
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
@@ -246,6 +249,8 @@ Expected<bool> LockFileManager::tryLock() {
}
LockFileManager::~LockFileManager() {
+ auto SandboxBypass = sys::sandbox_scoped_disable();
+
if (!std::holds_alternative<OwnedByUs>(Owner))
return;
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index d6d7b8715bd44..4d8e878511705 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"
@@ -553,6 +554,8 @@ Error OnDiskOutputFile::keep() {
}
Error OnDiskOutputFile::discard() {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+
// Destroy the streams to flush them.
if (auto E = reset())
return E;
@@ -582,6 +585,8 @@ Error OnDiskOutputBackend::makeAbsolute(SmallVectorImpl<char> &Path) const {
Expected<std::unique_ptr<OutputFileImpl>>
OnDiskOutputBackend::createFileImpl(StringRef Path,
std::optional<OutputConfig> Config) {
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+
SmallString<256> AbsPath;
if (Path != "-") {
AbsPath = Path;
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 07b99896543bd..0ea5f024c82c5 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"
@@ -617,6 +618,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`.
+ auto BypassSandbox = sys::sandbox_scoped_disable();
+
if (FD < 0 ) {
ShouldClose = false;
return;
>From defc8fde81221f73c5c7ea6c3e92f48daef7dfa1 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 15 Jul 2025 15:50:29 -0700
Subject: [PATCH 07/11] [llvm][clang] Sandbox IO operations (getcwd)
---
llvm/lib/Support/IOSandboxInternal.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 044b7dd9bd781..9e7bb7d6f4567 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -51,6 +51,7 @@ static constexpr auto readdir = detail::interpose(::readdir);
static constexpr auto stat = detail::interpose(::stat);
static constexpr auto lstat = detail::interpose(::lstat);
static constexpr auto fstat = detail::interpose(::fstat);
+static constexpr auto getcwd = detail::interpose(::getcwd);
} // namespace llvm
#endif
>From 35f7f1652d94d84911949108772c4ba5409f6f7b Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 15 Jul 2025 15:51:46 -0700
Subject: [PATCH 08/11] [llvm][clang] Sandbox IO operations (realpath)
---
llvm/lib/Support/IOSandboxInternal.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 9e7bb7d6f4567..80fa79220cc54 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -52,6 +52,7 @@ static constexpr auto stat = detail::interpose(::stat);
static constexpr auto lstat = detail::interpose(::lstat);
static constexpr auto fstat = detail::interpose(::fstat);
static constexpr auto getcwd = detail::interpose(::getcwd);
+static constexpr auto realpath = detail::interpose(::realpath);
} // namespace llvm
#endif
>From fb3e6e85fa383e22bf03c679fd5d1ec6af5812bb Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 15 Jul 2025 15:52:09 -0700
Subject: [PATCH 09/11] [llvm][clang] Sandbox IO operations (readlink)
---
llvm/lib/Support/IOSandboxInternal.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index 80fa79220cc54..b7b8b10a87e78 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -53,6 +53,7 @@ static constexpr auto lstat = detail::interpose(::lstat);
static constexpr auto fstat = detail::interpose(::fstat);
static constexpr auto getcwd = detail::interpose(::getcwd);
static constexpr auto realpath = detail::interpose(::realpath);
+static constexpr auto readlink = detail::interpose(::readlink);
} // namespace llvm
#endif
>From 69614a7d71fc3c58b5fa071779168472aa924f65 Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Tue, 15 Jul 2025 15:52:51 -0700
Subject: [PATCH 10/11] [llvm][clang] Sandbox IO operations (access)
---
llvm/lib/Support/IOSandboxInternal.h | 1 +
llvm/lib/Support/Unix/Path.inc | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
index b7b8b10a87e78..3e953c53c6e2a 100644
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ b/llvm/lib/Support/IOSandboxInternal.h
@@ -48,6 +48,7 @@ static constexpr auto read = detail::interpose(::read);
static constexpr auto pread = detail::interpose(::pread);
static constexpr auto mmap = detail::interpose(::mmap);
static constexpr auto readdir = detail::interpose(::readdir);
+static constexpr auto access = detail::interpose(::access);
static constexpr auto stat = detail::interpose(::stat);
static constexpr auto lstat = detail::interpose(::lstat);
static constexpr auto fstat = detail::interpose(::fstat);
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index fa27f86241b7d..f51c847a5f457 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -623,7 +623,7 @@ std::error_code access(const Twine &Path, AccessMode Mode) {
SmallString<128> PathStorage;
StringRef P = Path.toNullTerminatedStringRef(PathStorage);
- if (::access(P.begin(), convertAccessMode(Mode)) == -1)
+ if (llvm::access(P.begin(), convertAccessMode(Mode)) == -1)
return errnoAsErrorCode();
if (Mode == AccessMode::Execute) {
@@ -978,7 +978,7 @@ ErrorOr<basic_file_status> directory_entry::status() const {
static bool hasProcSelfFD() {
// If we have a /proc filesystem mounted, we can quickly establish the
// real name of the file with readlink
- static const bool Result = (access("/proc/self/fd", R_OK) == 0);
+ static const bool Result = (llvm::access("/proc/self/fd", R_OK) == 0);
return Result;
}
#endif
>From a3307cd9721bb02c1d4406c16e1aa9f6d54d11fb Mon Sep 17 00:00:00 2001
From: Jan Svoboda <jan_svoboda at apple.com>
Date: Wed, 1 Oct 2025 15:44:03 -0700
Subject: [PATCH 11/11] Rename, re-layer, add build setting
---
clang/lib/CodeGen/BackendUtil.cpp | 2 +-
clang/lib/Driver/Driver.cpp | 2 +-
clang/lib/Driver/Job.cpp | 2 +-
clang/lib/Serialization/GlobalModuleIndex.cpp | 4 +-
clang/lib/Serialization/ModuleCache.cpp | 4 +-
.../StaticAnalyzer/Core/HTMLDiagnostics.cpp | 2 +-
clang/tools/driver/cc1_main.cpp | 4 +-
clang/tools/driver/cc1as_main.cpp | 4 +-
llvm/CMakeLists.txt | 1 +
llvm/include/llvm/Support/IOSandbox.h | 72 +++++++++++++++++--
llvm/lib/Support/IOSandbox.cpp | 19 -----
llvm/lib/Support/IOSandboxInternal.h | 60 ----------------
llvm/lib/Support/LockFileManager.cpp | 4 +-
llvm/lib/Support/Signals.cpp | 2 +-
llvm/lib/Support/Unix/Path.inc | 26 ++++++-
llvm/lib/Support/VirtualFileSystem.cpp | 20 +++---
llvm/lib/Support/VirtualOutputBackends.cpp | 4 +-
llvm/lib/Support/raw_ostream.cpp | 2 +-
18 files changed, 121 insertions(+), 113 deletions(-)
delete mode 100644 llvm/lib/Support/IOSandbox.cpp
delete mode 100644 llvm/lib/Support/IOSandboxInternal.h
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index a4a238ecc5c75..d3f8579260f71 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1414,7 +1414,7 @@ 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.
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ 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.
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index c75a46dc906d8..f873276cc330c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1872,7 +1872,7 @@ bool Driver::getCrashDiagnosticFile(StringRef ReproCrashFilename,
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.
- auto BypassSandbox = sandbox_scoped_disable();
+ 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
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 4f44864bef1ac..c5d4825da4957 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -428,7 +428,7 @@ int CC1Command::Execute(ArrayRef<std::optional<StringRef>> Redirects,
// Enabling the sandbox here allows us to restore its previous state even when
// this cc1 invocation crashes.
- auto EnableSandbox = llvm::sys::sandbox_scoped_enable();
+ auto EnableSandbox = llvm::sys::sandbox::scopedEnable();
llvm::CrashRecoveryContext CRC;
CRC.DumpStackAndCleanupOnFailure = true;
diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp
index 99d90054cb09f..2246a3ac0a57e 100644
--- a/clang/lib/Serialization/GlobalModuleIndex.cpp
+++ b/clang/lib/Serialization/GlobalModuleIndex.cpp
@@ -252,7 +252,7 @@ GlobalModuleIndex::~GlobalModuleIndex() {
std::pair<GlobalModuleIndex *, llvm::Error>
GlobalModuleIndex::readIndex(StringRef Path) {
// This is a compiler-internal input/output, let's bypass the sandbox.
- auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
// Load the index file, if it's there.
llvm::SmallString<128> IndexPath;
@@ -848,7 +848,7 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,
const PCHContainerReader &PCHContainerRdr,
StringRef Path) {
// This is a compiler-internal input/output, let's bypass the sandbox.
- auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
llvm::SmallString<128> IndexPath;
IndexPath += Path;
diff --git a/clang/lib/Serialization/ModuleCache.cpp b/clang/lib/Serialization/ModuleCache.cpp
index 021068c806ca6..21f672ee82590 100644
--- a/clang/lib/Serialization/ModuleCache.cpp
+++ b/clang/lib/Serialization/ModuleCache.cpp
@@ -29,7 +29,7 @@ void clang::maybePruneImpl(StringRef Path, time_t PruneInterval,
return;
// This is a compiler-internal input/output, let's bypass the sandbox.
- auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
llvm::SmallString<128> TimestampFile(Path);
llvm::sys::path::append(TimestampFile, "modules.timestamp");
@@ -120,7 +120,7 @@ class CrossProcessModuleCache : public ModuleCache {
std::time_t getModuleTimestamp(StringRef ModuleFilename) override {
// This is a compiler-internal input/output, let's bypass the sandbox.
- auto SandboxBypass = llvm::sys::sandbox_scoped_disable();
+ auto SandboxBypass = llvm::sys::sandbox::scopedDisable();
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(ModuleFilename, Status) != std::error_code{})
return 0;
diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
index 11e53a5132563..aae4f4161fad4 100644
--- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
+++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
@@ -259,7 +259,7 @@ void HTMLDiagnostics::FlushDiagnosticsImpl(
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
FilesMade *filesMade) {
// FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
- auto SandboxBypass = llvm::sys::sandbox_scoped_disable();
+ auto SandboxBypass = llvm::sys::sandbox::scopedDisable();
// Create the HTML directory if it is missing.
if (!createdDir) {
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index af30ba68dfde4..579b441e5cb9c 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -274,7 +274,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
/// Create the actual file system.
auto VFS = [] {
- auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
return llvm::vfs::getRealFileSystem();
}();
Clang->createVirtualFileSystem(std::move(VFS), DiagsBuffer);
@@ -309,7 +309,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
// results now. This happens in -disable-free mode.
{
// This isn't a formal input or output of the compiler.
- auto BypassSandbox = llvm::sys::sandbox_scoped_disable();
+ auto BypassSandbox = llvm::sys::sandbox::scopedDisable();
std::unique_ptr<raw_ostream> IOFile = llvm::CreateInfoOutputFile();
if (Clang->getCodeGenOpts().TimePassesJson) {
*IOFile << "{\n";
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index 5e1699f96cb36..edbfba1298d7a 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -427,7 +427,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = [=] {
// FIXME(sandboxing): Make this a proper input file.
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
return MemoryBuffer::getFileOrSTDIN(Opts.InputFile, /*IsText=*/true);
}();
@@ -674,7 +674,7 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagClient);
auto VFS = [] {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
return vfs::getRealFileSystem();
}();
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index c450ee5a3d72e..ac81506a02993 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -697,6 +697,7 @@ option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
option(LLVM_ENABLE_DUMP "Enable dump functions even when assertions are disabled" OFF)
option(LLVM_UNREACHABLE_OPTIMIZE "Optimize llvm_unreachable() as undefined behavior (default), guaranteed trap when OFF" ON)
+option(LLVM_ENABLE_IO_SANDBOX "Enable IO sandboxing in supported tools" OFF)
if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" )
option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF)
diff --git a/llvm/include/llvm/Support/IOSandbox.h b/llvm/include/llvm/Support/IOSandbox.h
index 1a8fb9788e3f6..cf6f4f2b857a0 100644
--- a/llvm/include/llvm/Support/IOSandbox.h
+++ b/llvm/include/llvm/Support/IOSandbox.h
@@ -9,12 +9,74 @@
#ifndef LLVM_SUPPORT_IOSANDBOX_H
#define LLVM_SUPPORT_IOSANDBOX_H
+// Always enable IO sandboxing in debug/assert builds for development,
+// but allow enablement even for release/no-assert builds for production.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_IO_SANDBOX)
+
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
-namespace llvm::sys {
-SaveAndRestore<bool> sandbox_scoped_enable();
-SaveAndRestore<bool> sandbox_scoped_disable();
-void sandbox_violation_if_enabled();
-} // namespace llvm::sys
+namespace llvm::sys::sandbox {
+inline thread_local bool Enabled = false;
+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 {
+inline int scopedEnable() {}
+inline int scopedDisable() {}
+inline void violationIfEnabled() {}
+} // namespace llvm::sys::sandbox
+
+#endif
+
+namespace llvm::sys::sandbox {
+/// Facility for seamlessly interposing function calls and sandbox enforcement.
+/// This is intended for creating static functors like so:
+///
+/// // before
+/// #include <unistd.h>
+/// namespace x {
+/// void perform_read() { read(); } // not sandboxed
+/// }
+///
+/// // after
+/// #include <unistd.h>
+/// namespace x {
+/// static constexpr auto read = llvm::sys::sandbox::interpose(::read);
+/// void perform_read() { read(); } // sandboxed
+/// }
+template <class FnTy> struct Interposed;
+
+template <class RetTy, class... ArgTy> struct Interposed<RetTy (*)(ArgTy...)> {
+ RetTy (*Fn)(ArgTy...);
+
+ RetTy operator()(ArgTy... Arg) const {
+ violationIfEnabled();
+ return Fn(std::forward<ArgTy>(Arg)...);
+ }
+};
+
+template <class RetTy, class... ArgTy>
+struct Interposed<RetTy (*)(ArgTy..., ...)> {
+ RetTy (*Fn)(ArgTy..., ...);
+
+ template <class... CVarArgTy>
+ RetTy operator()(ArgTy... Arg, CVarArgTy... CVarArg) const {
+ violationIfEnabled();
+ return Fn(std::forward<ArgTy>(Arg)..., std::forward<CVarArgTy>(CVarArg)...);
+ }
+};
+
+template <class FnTy> constexpr auto interpose(FnTy Fn) {
+ return Interposed<FnTy>{Fn};
+}
+} // namespace llvm::sys::sandbox
#endif
diff --git a/llvm/lib/Support/IOSandbox.cpp b/llvm/lib/Support/IOSandbox.cpp
deleted file mode 100644
index a046d38b48fc3..0000000000000
--- a/llvm/lib/Support/IOSandbox.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "llvm/Support/IOSandbox.h"
-
-#include <cassert>
-
-using namespace llvm;
-
-thread_local bool IOSandboxEnabled = false;
-
-SaveAndRestore<bool> sys::sandbox_scoped_enable() {
- return {IOSandboxEnabled, true};
-}
-
-SaveAndRestore<bool> sys::sandbox_scoped_disable() {
- return {IOSandboxEnabled, false};
-}
-
-void sys::sandbox_violation_if_enabled() {
- assert(!IOSandboxEnabled && "sandbox violation");
-}
diff --git a/llvm/lib/Support/IOSandboxInternal.h b/llvm/lib/Support/IOSandboxInternal.h
deleted file mode 100644
index 3e953c53c6e2a..0000000000000
--- a/llvm/lib/Support/IOSandboxInternal.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef LLVM_SUPPORT_IOSANDBOXINTERNAL_H
-#define LLVM_SUPPORT_IOSANDBOXINTERNAL_H
-
-#include "llvm/Support/IOSandbox.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-#include <dirent.h>
-
-extern thread_local bool IOSandboxEnabled;
-
-namespace llvm {
-namespace detail {
-template <class FnTy> struct Interposed;
-
-template <class RetTy, class... ArgTy> struct Interposed<RetTy (*)(ArgTy...)> {
- RetTy (*Fn)(ArgTy...);
-
- RetTy operator()(ArgTy... Arg) const {
- sys::sandbox_violation_if_enabled();
- return Fn(std::forward<ArgTy>(Arg)...);
- }
-};
-
-template <class RetTy, class... ArgTy>
-struct Interposed<RetTy (*)(ArgTy..., ...)> {
- RetTy (*Fn)(ArgTy..., ...);
-
- template <class... CVarArgTy>
- RetTy operator()(ArgTy... Arg, CVarArgTy... CVarArg) const {
- sys::sandbox_violation_if_enabled();
- return Fn(std::forward<ArgTy>(Arg)..., std::forward<CVarArgTy>(CVarArg)...);
- }
-};
-
-template <class FnTy> constexpr auto interpose(FnTy Fn) {
- return Interposed<FnTy>{Fn};
-}
-} // namespace detail
-
-static constexpr auto read = detail::interpose(::read);
-static constexpr auto pread = detail::interpose(::pread);
-static constexpr auto mmap = detail::interpose(::mmap);
-static constexpr auto readdir = detail::interpose(::readdir);
-static constexpr auto access = detail::interpose(::access);
-static constexpr auto stat = detail::interpose(::stat);
-static constexpr auto lstat = detail::interpose(::lstat);
-static constexpr auto fstat = detail::interpose(::fstat);
-static constexpr auto getcwd = detail::interpose(::getcwd);
-static constexpr auto realpath = detail::interpose(::realpath);
-static constexpr auto readlink = detail::interpose(::readlink);
-} // namespace llvm
-
-#endif
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index 54c42e4dd53e6..795bffbbc648c 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -52,7 +52,7 @@ using namespace llvm;
/// \returns The process ID of the process that owns this lock file
std::optional<LockFileManager::OwnedByAnother>
LockFileManager::readLockFile(StringRef LockFileName) {
- auto SandboxBypass = sys::sandbox_scoped_disable();
+ auto SandboxBypass = sys::sandbox::scopedDisable();
// Read the owning host and PID out of the lock file. If it appears that the
// owning process is dead, the lock file is invalid.
@@ -249,7 +249,7 @@ Expected<bool> LockFileManager::tryLock() {
}
LockFileManager::~LockFileManager() {
- auto SandboxBypass = sys::sandbox_scoped_disable();
+ auto SandboxBypass = sys::sandbox::scopedDisable();
if (!std::holds_alternative<OwnedByUs>(Owner))
return;
diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp
index 076ec293750af..f160a135f623d 100644
--- a/llvm/lib/Support/Signals.cpp
+++ b/llvm/lib/Support/Signals.cpp
@@ -97,7 +97,7 @@ CallBacksToRun() {
// Signal-safe.
void sys::RunSignalHandlers() {
// Let's not interfere with stack trace symbolication and friends.
- auto BypassSandbox = sandbox_scoped_disable();
+ auto BypassSandbox = sandbox::scopedDisable();
for (CallbackAndCookie &RunMe : CallBacksToRun()) {
auto Expected = CallbackAndCookie::Status::Initialized;
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index f51c847a5f457..ba99c07f3b463 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -114,7 +114,31 @@ typedef uint_t uint;
#define STATVFS_F_FLAG(vfs) (vfs).f_flags
#endif
-#include "IOSandboxInternal.h"
+#include <stdio.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <dirent.h>
+
+#include "llvm/Support/IOSandbox.h"
+
+namespace llvm {
+static constexpr auto read = sys::sandbox::interpose(::read);
+static constexpr auto pread = sys::sandbox::interpose(::pread);
+static constexpr auto mmap = sys::sandbox::interpose(::mmap);
+static constexpr auto readdir = sys::sandbox::interpose(::readdir);
+static constexpr auto access = sys::sandbox::interpose(::access);
+static constexpr auto stat = sys::sandbox::interpose(::stat);
+static constexpr auto lstat = sys::sandbox::interpose(::lstat);
+static constexpr auto fstat = sys::sandbox::interpose(::fstat);
+static constexpr auto getcwd = sys::sandbox::interpose(::getcwd);
+static constexpr auto realpath = sys::sandbox::interpose(::realpath);
+static constexpr auto readlink = sys::sandbox::interpose(::readlink);
+} // namespace llvm
using namespace llvm;
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index ecd50a8004f70..62fe07d3e4af0 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -222,7 +222,7 @@ RealFile::~RealFile() { close(); }
ErrorOr<Status> RealFile::status() {
assert(FD != kInvalidFile && "cannot stat closed file");
if (!S.isStatusKnown()) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
file_status RealStatus;
if (std::error_code EC = sys::fs::status(FD, RealStatus))
return EC;
@@ -239,7 +239,7 @@ ErrorOr<std::unique_ptr<MemoryBuffer>>
RealFile::getBuffer(const Twine &Name, int64_t FileSize,
bool RequiresNullTerminator, bool IsVolatile) {
assert(FD != kInvalidFile && "cannot get buffer for closed file");
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
return MemoryBuffer::getOpenFile(FD, Name, FileSize, RequiresNullTerminator,
IsVolatile);
}
@@ -309,7 +309,7 @@ class RealFileSystem : public FileSystem {
ErrorOr<std::unique_ptr<File>>
openFileForReadWithFlags(const Twine &Name, sys::fs::OpenFlags Flags) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
SmallString<256> RealName, Storage;
Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead(
adjustPath(Name, Storage), Flags, &RealName);
@@ -331,7 +331,7 @@ class RealFileSystem : public FileSystem {
} // namespace
ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
SmallString<256> Storage;
sys::fs::file_status RealStatus;
if (std::error_code EC =
@@ -356,7 +356,7 @@ llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const {
if (WD)
return WD->getError();
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
SmallString<128> Dir;
if (std::error_code EC = llvm::sys::fs::current_path(Dir))
return EC;
@@ -387,7 +387,7 @@ std::error_code RealFileSystem::isLocal(const Twine &Path, bool &Result) {
std::error_code RealFileSystem::getRealPath(const Twine &Path,
SmallVectorImpl<char> &Output) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
SmallString<256> Storage;
return llvm::sys::fs::real_path(adjustPath(Path, Storage), Output);
}
@@ -406,12 +406,12 @@ void RealFileSystem::printImpl(raw_ostream &OS, PrintType Type,
IntrusiveRefCntPtr<FileSystem> vfs::getRealFileSystem() {
static IntrusiveRefCntPtr<FileSystem> FS =
makeIntrusiveRefCnt<RealFileSystem>(true);
- sys::sandbox_violation_if_enabled();
+ sys::sandbox::violationIfEnabled();
return FS;
}
std::unique_ptr<FileSystem> vfs::createPhysicalFileSystem() {
- sys::sandbox_violation_if_enabled();
+ sys::sandbox::violationIfEnabled();
return std::make_unique<RealFileSystem>(false);
}
@@ -422,14 +422,14 @@ class RealFSDirIter : public llvm::vfs::detail::DirIterImpl {
public:
RealFSDirIter(const Twine &Path, std::error_code &EC) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
Iter = llvm::sys::fs::directory_iterator{Path, EC};
if (Iter != llvm::sys::fs::directory_iterator())
CurrentEntry = directory_entry(Iter->path(), Iter->type());
}
std::error_code increment() override {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
std::error_code EC;
Iter.increment(EC);
CurrentEntry = (Iter == llvm::sys::fs::directory_iterator())
diff --git a/llvm/lib/Support/VirtualOutputBackends.cpp b/llvm/lib/Support/VirtualOutputBackends.cpp
index 4d8e878511705..2302f1fce0b57 100644
--- a/llvm/lib/Support/VirtualOutputBackends.cpp
+++ b/llvm/lib/Support/VirtualOutputBackends.cpp
@@ -554,7 +554,7 @@ Error OnDiskOutputFile::keep() {
}
Error OnDiskOutputFile::discard() {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
// Destroy the streams to flush them.
if (auto E = reset())
@@ -585,7 +585,7 @@ Error OnDiskOutputBackend::makeAbsolute(SmallVectorImpl<char> &Path) const {
Expected<std::unique_ptr<OutputFileImpl>>
OnDiskOutputBackend::createFileImpl(StringRef Path,
std::optional<OutputConfig> Config) {
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
SmallString<256> AbsPath;
if (Path != "-") {
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp
index 0ea5f024c82c5..3b608706f6c55 100644
--- a/llvm/lib/Support/raw_ostream.cpp
+++ b/llvm/lib/Support/raw_ostream.cpp
@@ -619,7 +619,7 @@ 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`.
- auto BypassSandbox = sys::sandbox_scoped_disable();
+ auto BypassSandbox = sys::sandbox::scopedDisable();
if (FD < 0 ) {
ShouldClose = false;
More information about the llvm-commits
mailing list