blob: 85c4a9a181c454c983ad69ec3983e5e648e8aabe [file] [log] [blame]
Dan Willemsen269a8c72017-05-03 17:15:47 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package build
16
Dan Willemsen63663c62019-01-02 12:24:44 -080017import (
18 "bytes"
19 "os"
20 "os/exec"
21 "os/user"
22 "strings"
23 "sync"
Dan Willemsen269a8c72017-05-03 17:15:47 -070024)
25
Dan Willemsen63663c62019-01-02 12:24:44 -080026type 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
Dan Willemsen269a8c72017-05-03 17:15:47 -070055func (c *Cmd) sandboxSupported() bool {
Dan Willemsen63663c62019-01-02 12:24:44 -080056 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
Dan Willemsen269a8c72017-05-03 17:15:47 -0700108}
109
110func (c *Cmd) wrapSandbox() {
Dan Willemsen63663c62019-01-02 12:24:44 -0800111 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
Dan Willemsen3a4dbd62019-01-16 23:02:24 -0800130 // Mount /proc read-write, necessary to run a nested nsjail or minijail0
131 "--proc_rw",
132
Dan Willemsen63663c62019-01-02 12:24:44 -0800133 // Use a consistent user & group.
134 // Note that these are mapped back to the real UID/GID when
135 // doing filesystem operations, so they're rather arbitrary.
136 "-u", "nobody",
137 "-g", sandboxConfig.group,
138
139 // Set high values, as nsjail uses low defaults.
140 "--rlimit_as", "soft",
141 "--rlimit_core", "soft",
142 "--rlimit_cpu", "soft",
143 "--rlimit_fsize", "soft",
144 "--rlimit_nofile", "soft",
145
146 // For now, just map everything. Eventually we should limit this, especially to make most things readonly.
147 "-B", "/",
148
Dan Willemsen63663c62019-01-02 12:24:44 -0800149 // 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)
Dan Willemsen269a8c72017-05-03 17:15:47 -0700167}