-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Rework the Sandbox
enum into a SandboxProfile
struct that can separate out point of configuration from point of application
#4005
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
Conversation
@@ -1361,6 +1370,7 @@ final class PackageToolTests: CommandsTestCase { | |||
let output = try result.utf8Output() + result.utf8stderrOutput() | |||
XCTAssertEqual(result.exitStatus, .terminated(code: 0), "output: \(output)") | |||
XCTAssertMatch(output, .contains("This is MyCommandPlugin.")) | |||
XCTAssertMatch(output, .contains("successfully created file at path \(resolveSymlinks(packageDir).appending(components: ".build", "plugins", "outputs", "Foo"))")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the check that was incomplete in the previous test, and would have caught the problem.
@swift-ci smoke test |
0b631ed
to
836aabb
Compare
@swift-ci smoke test |
Tests/BasicsTests/SandboxTests.swift
Outdated
} | ||
} | ||
|
||
func testWritingToWritableInsideReadOnlyAllowed() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This adds a specific test case for a writable directory inside of a read-only directory.
let strictness: Sandbox.Strictness = toolsVersion < .v5_3 ? .manifest_pre_53 : .default | ||
cmd = Sandbox.apply(command: cmd, strictness: strictness, writableDirectories: cacheDirectories) | ||
let sandboxProfile = SandboxProfile(pathRules: cacheDirectories.map{ .writable($0) }) | ||
cmd = sandboxProfile.apply(to: cmd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The notes in the Sandbox profile generator indicate that the pre-5.3 rules were needed for interpreting the manifest rather than compiling and running it. This isn't supported anymore, and the operations affected were being able to write to some Clang locations and to set sysctl
s. Those don't seem like operations that we want to keep supporting. Do we know of any packages that required the < 5.3 strictness?
836aabb
to
692e86a
Compare
@swift-ci smoke test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<3 this is great
@swift-ci please test package compatibility |
Hmm...
|
<pkgdir>/.build
Sandbox
enum into a SandboxProfile
struct that can separate out point of configuration from point of application
Moving this one aside temporarily while preparing a much smaller fix for the problem at hand. That fix can then be nominated for inclusion in 5.6. Then I'll bring this back since it's what we want to do moving forward. |
@swift-ci please test package compatibility |
16e9075
to
af586c4
Compare
@swift-ci please smoke test |
af586c4
to
ccdc849
Compare
…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 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()` will be respected all the way through. As part of this we also take the opportunity to clean up the interface a little. In particular, this change turns 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 - 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 - there is separate control for whether or not to allow network access The new `SandboxProfile` is also a bit more ergonomic — as a struct, it can be copied, mutated, and carried around in a property before being used. 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. 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. rdar://91575256
ccdc849
to
e32cba8
Compare
Opened a new PR here: #4307 that replaces this one |
This change turns the stateless Sandbox enum into a SandboxProfile struct that can be configured and passed around well before being applied, and it makes the configuration more flexible in several regards:
allow
anddeny
rulesstrictness
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.Motivation
Separating out the point of configuration from the point of application of the sandbox makes it easier to configure.
The ergonomic changes described above also make it easier to use.
Having the sandbox profile be a struct that generates the platform specifics as needed also provides a place with which to associate any cached/compiled representation for profiles that are largely static.
Details
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.
In this commit, the call sites have been adjusted so that they use the modified SandboxProfile API, but still construct the profiles on-the-fly as before. A future change could make them instead be configured at an early point and then applied later when the sandboxed process is actually launched. 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.