Skip to content

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

abertelrud
Copy link
Contributor

@abertelrud abertelrud commented Apr 19, 2022

The sandbox used for manifests and plugins currently allows unrestricted access to /tmp as well as to the directory returned by NSTemporaryDirectory(). It would be safer to just provide the directory returned by NSTemporaryDirectory(). Since and most tools look at TMPDIR, 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 by NSTemporaryDirectory().

Details

We can improve several things here by passing through the result of calling NSTemporaryDirectory() in the sandbox instead of /tmp and also setting 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.

If TMPDIR is set in SwiftPM's own environment, it will control SwiftPM's own NSTemporaryDirectory(), 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 to Process as an option to set TMPDIR in the environment of the subprocess (as indeed it would also make sense to extend Process to allow it to take a Sandbox profile in the first place; enabling the option to set TMPDIR 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 the Process launch).

Changes

  • remove /tmp from the Sandbox profiles
  • adjust a unit test to check that /tmp isn't writable

rdar://91575256

@abertelrud abertelrud self-assigned this Apr 19, 2022
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud marked this pull request as draft April 19, 2022 21:35
@abertelrud abertelrud force-pushed the eng/91575256-sandbox-improvements branch 2 times, most recently from 780bbd9 to 0963c8d Compare April 19, 2022 22:25
@abertelrud abertelrud marked this pull request as ready for review April 19, 2022 22:26
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud added the ready Author believes the PR is ready to be merged & any feedback has been addressed label Apr 20, 2022
@abertelrud abertelrud requested a review from tomerd April 20, 2022 16:59
@abertelrud abertelrud force-pushed the eng/91575256-sandbox-improvements branch from 0963c8d to 6440584 Compare April 20, 2022 17:34
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

1 similar comment
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud
Copy link
Contributor Author

Putting back to Draft — I'm going to fix the localFileSystem uses and the ugliness of having to separately set TMPDIR.

@abertelrud abertelrud marked this pull request as draft April 20, 2022 19:03
@abertelrud abertelrud removed the ready Author believes the PR is ready to be merged & any feedback has been addressed label Apr 21, 2022
@abertelrud abertelrud added WIP Work in progress DO NOT MERGE labels Apr 21, 2022
@abertelrud
Copy link
Contributor Author

Since this PR has a couple of separate changes, I will be pulling them out into separate PRs.

@abertelrud abertelrud added next waiting for next merge window and removed DO NOT MERGE labels Apr 25, 2022
@abertelrud
Copy link
Contributor Author

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.

@abertelrud
Copy link
Contributor Author

My word, there are a lot of merge conflicts now... :)

@abertelrud
Copy link
Contributor Author

abertelrud commented Nov 1, 2022

I have rebased onto main, resolved the conflicts, and put up the PR #5857 with just the Sandbox API changes from this PR. I'll then put up a separate PR for the TMPDIR change that builds on top of this, as they required some more discussion.

@abertelrud abertelrud force-pushed the eng/91575256-sandbox-improvements branch from fa71720 to c429e2e Compare November 1, 2022 16:23
… 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.
@abertelrud abertelrud force-pushed the eng/91575256-sandbox-improvements branch from c429e2e to 0bd9968 Compare November 1, 2022 16:57
@abertelrud abertelrud removed WIP Work in progress next waiting for next merge window labels Nov 1, 2022
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud
Copy link
Contributor Author

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
@abertelrud abertelrud force-pushed the eng/91575256-sandbox-improvements branch from 0bd9968 to 273865b Compare November 2, 2022 03:31
@abertelrud
Copy link
Contributor Author

@swift-ci please smoke test

@abertelrud abertelrud marked this pull request as ready for review November 2, 2022 03:31
@abertelrud abertelrud marked this pull request as draft January 3, 2023 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants