[clang] [llvm] [clang] Allow enabling sandbox for direct `-cc1` invocations (PR #174653)

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 7 09:30:41 PST 2026


================
@@ -264,8 +265,10 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
   }
 
   // Handle -cc1 integrated tools.
-  if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1"))
+  if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1")) {
+    auto EnableSandbox = llvm::sys::sandbox::scopedEnable();
----------------
jansvoboda11 wrote:

You're raising a valid point. I looked into this more closely and there seem to be 5 ways `cc1_main()` can be reached.

1. `clang -cc1 -emit-obj` - frontend invocation,
2. `clang -fintegrated-cc1 -c` - driver invocation with integrated -cc1 and single job,
3. `clang -fintegrated-cc1` - driver invocation with integrated -cc1 and multiple jobs,
4. `clang -fno-integrated-cc1 -c` - driver invocation without integrated -cc1 and single job,
5. `clang -fino-ntegrated-cc1` - driver invocation without integrated -cc1 and multiple jobs.

---

This PR clearly handles case (1):
* `clang_main()`
* `ExecuteCC1Tool()`
* `cc1_main()`

---

The original PR [#165350](https://github.com/llvm/llvm-project/pull/165350) handled case (2):
   * `clang_main()`
   * `Driver::ExecuteCompilation()`
   * ...
   * `CC1Command::Execute()`

The original PR enabled the sandbox in `CC1Command::Execute()` which is reached like so:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/tools/driver/driver.cpp#L371-L372

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/ToolChains/Clang.cpp#L7985-L7989

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/Job.cpp#L432

---

Interestingly, in case (3), with multiple jobs generated by the driver, this code:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/Driver.cpp#L5348-L5352

makes `CC1Command` forward to the regular (out-of-process) `Command`:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/Job.cpp#L410-L414

This means the new `-cc1` process will go down the path this PR handles and the sandbox will be enabled.

---

The same thing then happens in cases (4) and (5), without integrated `-cc1`, where this branch is not entered:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/tools/driver/driver.cpp#L371-L372

and then Clang creates a plain `Command` instead of `CC1Command`:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/ToolChains/Clang.cpp#L7990-L7994

and again, the new `-cc1` process will go down the path handled in this PR.

---

So I believe this PR makes sandboxing of `-cc1` commands work as intended, but maybe in a somewhat convoluted way. I think a simpler way to reliably enable sandbox for `cc1_main()` might be to do so right at the start of `cc1_main()` itself, regardless of how it was reached. However, I think this call to `scopedEnable()`:

https://github.com/llvm/llvm-project/blob/52f85b0159d7f9cd3f21d644e92684afc53f0ed1/clang/lib/Driver/Job.cpp#L430-L432

is still necessary, so that in case `cc1_main()` crashes and doesn't get a chance to restore the original sandbox setting itself in case (2), the sandbox is not unintentionally left enabled for the rest of the driver process. (But maybe we should consider moving the "restore previous sandbox setting" logic into `llvm::CrashRecoveryContext` that gets used for this case?)

Let me know what you think @benlangmuir.

https://github.com/llvm/llvm-project/pull/174653


More information about the cfe-commits mailing list