-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Sandbox for manifests and plugins should provide a unique path specified by TMPDIR
instead of allowing /tmp
#4307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Sandbox for manifests and plugins should provide a unique path specified by TMPDIR
instead of allowing /tmp
#4307
Conversation
@swift-ci please smoke test |
780bbd9
to
0963c8d
Compare
@swift-ci please smoke test |
0963c8d
to
6440584
Compare
@swift-ci please smoke test |
1 similar comment
@swift-ci please smoke test |
Putting back to Draft — I'm going to fix the |
Since this PR has a couple of separate changes, I will be pulling them out into separate PRs. |
I let this one sit for a long time, but it seems like high time to at least incorporate the SandboxProfile cleanup that doesn't change the TMPDIR semantics, since the cleanup seemed uncontroversial. |
My word, there are a lot of merge conflicts now... :) |
I have rebased onto |
fa71720
to
c429e2e
Compare
… struct that's easier to manage Turn the stateless `Sandbox` enum into a `SandboxProfile` struct that's a bit more flexible: - there is a list of path rules allowing a mixed order of `writable`, `readonly`, and `noaccess` rules; this addresses an issue where writable directories were always applied after readable directories, preventing arrangements where, for example, a source directory inside the temporary directory was properly made readonly - the defaults are built into the initializer rather than a separate `strictness` parameter — this means that they can be queried once the SandboxProfile has been created and are expressed in terms of the choices available to all sandbox profiles - it's a bit more ergonomic (as a struct, it can be copied, mutated, and carried around in a property before being used), and an optional `SandboxProfile` can be used to indicate both whether or not to apply a profile and if so what to apply. Having the sandbox profile be a struct that generates the platform specifics as needed also could also provide a place with which to associate any cached/compiled representation for profiles that are largely static, for any platform that supports that. As cleanup, this commit also removes the pre-SwiftPM 5.3 specialities which were specific to running the package manifest in an interpreter rather than compiling and executing it. This functionality is no longer relevant since it isn't possible to run any manifest in the interpreter, no matter what tools version the package specifies. In this commit, the call sites have been adjusted so that they use the modified SandboxProfile API, but they still construct the profiles on-the-fly as before. A future change will make them instead be configured at an early point and then applied later when the sandboxed process is actually launched. Note also that the existing call sites still pass `/tmp` because that it was the sandbox has allowed up until now. A separate PR will deal with whether or not allowing writes to `/tmp` is apprporiate. Another future change could add the sandbox profile to `Process` as a property so that there is no API assumption that applying a sandbox necessarily involves just modifying the command line.
c429e2e
to
0bd9968
Compare
@swift-ci please smoke test |
Oh right, the sandboxing is only a Darwin thing, so the test fails on other platforms. I'll fix that. |
…vide a unique path specified by `TMPDIR` The `/tmp` temporary directory is particularly unsafe because it is noisy — various processes with various ownerships write and read files there. So it's better to use the per-user directory returned by `NSTemporaryDirectory()`. We can improve several things here by passing through the result of calling `NSTemporaryDirectory()` in the sandbox instead of `/tmp`, and also `TMPDIR` in the environment (regardless of whether or not it was set in the inherited one). This will cause the inferior's use of Foundation to respect this directory (the implementation of `NSTemporaryDirectory()` looks at `TMPDIR` on all platforms), and that should also be true for any command line tools it calls, as long as it passes through the environment. Note: if `TMPDIR` happens to be set in SwiftPM's own environment, it will control SwiftPM's own uses of `NSTemporaryDirectory()`, so the callers `TMPDIR` will be respected all the way through (down to manifests and plugins). rdar://91575256
0bd9968
to
273865b
Compare
@swift-ci please smoke test |
The sandbox used for manifests and plugins currently allows unrestricted access to
/tmp
as well as to the directory returned byNSTemporaryDirectory()
. It would be safer to just provide the directory returned byNSTemporaryDirectory()
. Since and most tools look atTMPDIR
, this should not prevent doing anything that could be done before but provides better control of where temporary files go.Motivation
The
/tmp
temporary directory is particularly unsafe because it is noisy — various processes with various ownerships write and read files there. So it's better to use the per-user directory returned byNSTemporaryDirectory()
.Details
We can improve several things here by passing through the result of calling
NSTemporaryDirectory()
in the sandbox instead of/tmp
and also settingTMPDIR
in the environment (regardless of whether or not it was set in the inherited one). This will cause the inferior's use of Foundation to respect this directory (the implementation ofNSTemporaryDirectory()
looks atTMPDIR
on all platforms), and that should also be true for any command line tools it calls, as long as it passes through the environment.If
TMPDIR
is set in SwiftPM's own environment, it will control SwiftPM's ownNSTemporaryDirectory()
, and so the specified directory will be respected all the way through.Remarks
This builds on the improvements made in #5857, so it's better to review only the second commit that removes the writability of
/tmp
.Note that we don't gate this check on tools version as we usually do. When dealing with tightening a sandbox, it seems pointless to do so based on the tools version, since that allows any package to circumvent the change in perpetuity. This could indeed lead to some manifests or plugins requiring changes.
Also, I'm not delighted to make very similar modifications to four separate call sites. While I don't think special-casing
/tmp
should be part of the sandbox profile, I do think it would make sense to push this functionality down toProcess
as an option to setTMPDIR
in the environment of the subprocess (as indeed it would also make sense to extendProcess
to allow it to take a Sandbox profile in the first place; enabling the option to setTMPDIR
in the subprocess could then also add that as a writable directory in the Sandbox profile before applying it, making everything dealing with the temporary directory nicely packaged inside of theProcess
launch).Changes
/tmp
from the Sandbox profiles/tmp
isn't writablerdar://91575256