aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorDan Willemsen2019-01-02 14:24:44 -0600
committerDan Willemsen2019-01-15 15:47:31 -0600
commit63663c6bc9ee270e02b06ff3d4f8812f1ef4d49b (patch)
tree43841e3620caf538eb63f1061fd58e5741c920ea /ui
parent073941d780016e0770f083e1edd425739d15b80a (diff)
downloadplatform-build-soong-63663c6bc9ee270e02b06ff3d4f8812f1ef4d49b.tar.gz
platform-build-soong-63663c6bc9ee270e02b06ff3d4f8812f1ef4d49b.tar.xz
platform-build-soong-63663c6bc9ee270e02b06ff3d4f8812f1ef4d49b.zip
Implement linux sandboxing with nsjail
This really only initializes the sandbox, it does not attempt to change the view of the filesystem, nor does it turn off networking. Bug: 122270019 Test: m Test: trigger nsjail check failure; lunch; m; cat out/soong.log Test: USE_GOMA=true m libc Change-Id: Ib291072dcee8247c7a15f5b6831295ead6e4fc22
Diffstat (limited to 'ui')
-rw-r--r--ui/build/ninja.go1
-rw-r--r--ui/build/sandbox_darwin.go12
-rw-r--r--ui/build/sandbox_linux.go154
3 files changed, 151 insertions, 16 deletions
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 835f8203..cb41579c 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -59,6 +59,7 @@ func runNinja(ctx Context, config Config) {
59 "-w", "missingdepfile=err") 59 "-w", "missingdepfile=err")
60 60
61 cmd := Command(ctx, config, "ninja", executable, args...) 61 cmd := Command(ctx, config, "ninja", executable, args...)
62 cmd.Sandbox = ninjaSandbox
62 if config.HasKatiSuffix() { 63 if config.HasKatiSuffix() {
63 cmd.Environment.AppendFromKati(config.KatiEnvFile()) 64 cmd.Environment.AppendFromKati(config.KatiEnvFile())
64 } 65 }
diff --git a/ui/build/sandbox_darwin.go b/ui/build/sandbox_darwin.go
index 7e75167a..43c5480c 100644
--- a/ui/build/sandbox_darwin.go
+++ b/ui/build/sandbox_darwin.go
@@ -21,12 +21,12 @@ import (
21type Sandbox string 21type Sandbox string
22 22
23const ( 23const (
24 noSandbox = "" 24 noSandbox = ""
25 globalSandbox = "build/soong/ui/build/sandbox/darwin/global.sb" 25 globalSandbox = "build/soong/ui/build/sandbox/darwin/global.sb"
26 dumpvarsSandbox = globalSandbox 26 dumpvarsSandbox = globalSandbox
27 soongSandbox = globalSandbox 27 soongSandbox = globalSandbox
28 katiSandbox = globalSandbox 28 katiSandbox = globalSandbox
29 katiCleanSpecSandbox = globalSandbox 29 ninjaSandbox = noSandbox
30) 30)
31 31
32var sandboxExecPath string 32var sandboxExecPath string
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index f2bfac29..b87637f7 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -14,20 +14,154 @@
14 14
15package build 15package build
16 16
17type Sandbox bool 17import (
18 18 "bytes"
19const ( 19 "os"
20 noSandbox = false 20 "os/exec"
21 globalSandbox = false 21 "os/user"
22 dumpvarsSandbox = false 22 "strings"
23 soongSandbox = false 23 "sync"
24 katiSandbox = false
25 katiCleanSpecSandbox = false
26) 24)
27 25
26type Sandbox struct {
27 Enabled bool
28 DisableWhenUsingGoma bool
29}
30
31var (
32 noSandbox = Sandbox{}
33 basicSandbox = Sandbox{
34 Enabled: true,
35 }
36
37 dumpvarsSandbox = basicSandbox
38 katiSandbox = basicSandbox
39 soongSandbox = basicSandbox
40 ninjaSandbox = Sandbox{
41 Enabled: true,
42 DisableWhenUsingGoma: true,
43 }
44)
45
46const nsjailPath = "prebuilts/build-tools/linux-x86/bin/nsjail"
47
48var sandboxConfig struct {
49 once sync.Once
50
51 working bool
52 group string
53}
54
28func (c *Cmd) sandboxSupported() bool { 55func (c *Cmd) sandboxSupported() bool {
29 return false 56 if !c.Sandbox.Enabled {
57 return false
58 }
59
60 // Goma is incompatible with PID namespaces and Mount namespaces. b/122767582
61 if c.Sandbox.DisableWhenUsingGoma && c.config.UseGoma() {
62 return false
63 }
64
65 sandboxConfig.once.Do(func() {
66 sandboxConfig.group = "nogroup"
67 if _, err := user.LookupGroup(sandboxConfig.group); err != nil {
68 sandboxConfig.group = "nobody"
69 }
70
71 cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
72 "-H", "android-build",
73 "-e",
74 "-u", "nobody",
75 "-g", sandboxConfig.group,
76 "-B", "/",
77 "--disable_clone_newcgroup",
78 "--",
79 "/bin/bash", "-c", `if [ $(hostname) == "android-build" ]; then echo "Android" "Success"; else echo Failure; fi`)
80 cmd.Env = c.config.Environment().Environ()
81
82 c.ctx.Verboseln(cmd.Args)
83 data, err := cmd.CombinedOutput()
84 if err == nil && bytes.Contains(data, []byte("Android Success")) {
85 sandboxConfig.working = true
86 return
87 }
88
89 c.ctx.Println("Build sandboxing disabled due to nsjail error. This may become fatal in the future.")
90 c.ctx.Println("Please let us know why nsjail doesn't work in your environment at:")
91 c.ctx.Println(" https://groups.google.com/forum/#!forum/android-building")
92 c.ctx.Println(" https://issuetracker.google.com/issues/new?component=381517")
93
94 for _, line := range strings.Split(strings.TrimSpace(string(data)), "\n") {
95 c.ctx.Verboseln(line)
96 }
97
98 if err == nil {
99 c.ctx.Verboseln("nsjail exited successfully, but without the correct output")
100 } else if e, ok := err.(*exec.ExitError); ok {
101 c.ctx.Verbosef("nsjail failed with %v", e.ProcessState.String())
102 } else {
103 c.ctx.Verbosef("nsjail failed with %v", err)
104 }
105 })
106
107 return sandboxConfig.working
30} 108}
31 109
32func (c *Cmd) wrapSandbox() { 110func (c *Cmd) wrapSandbox() {
111 wd, _ := os.Getwd()
112
113 sandboxArgs := []string{
114 // The executable to run
115 "-x", c.Path,
116
117 // Set the hostname to something consistent
118 "-H", "android-build",
119
120 // Use the current working dir
121 "--cwd", wd,
122
123 // No time limit
124 "-t", "0",
125
126 // Keep all environment variables, we already filter them out
127 // in soong_ui
128 "-e",
129
130 // Use a consistent user & group.
131 // Note that these are mapped back to the real UID/GID when
132 // doing filesystem operations, so they're rather arbitrary.
133 "-u", "nobody",
134 "-g", sandboxConfig.group,
135
136 // Set high values, as nsjail uses low defaults.
137 "--rlimit_as", "soft",
138 "--rlimit_core", "soft",
139 "--rlimit_cpu", "soft",
140 "--rlimit_fsize", "soft",
141 "--rlimit_nofile", "soft",
142
143 // For now, just map everything. Eventually we should limit this, especially to make most things readonly.
144 "-B", "/",
145
146 // Enable networking for now. TODO: remove
147 "-N",
148
149 // Disable newcgroup for now, since it may require newer kernels
150 // TODO: try out cgroups
151 "--disable_clone_newcgroup",
152
153 // Only log important warnings / errors
154 "-q",
155
156 // Stop parsing arguments
157 "--",
158 }
159 c.Args = append(sandboxArgs, c.Args[1:]...)
160 c.Path = nsjailPath
161
162 env := Environment(c.Env)
163 if _, hasUser := env.Get("USER"); hasUser {
164 env.Set("USER", "nobody")
165 }
166 c.Env = []string(env)
33} 167}