|
6 | 6 | "io/ioutil"
|
7 | 7 | "os"
|
8 | 8 | "path/filepath"
|
| 9 | + "regexp" |
9 | 10 | "strconv"
|
10 | 11 | "strings"
|
11 | 12 | "testing"
|
@@ -44,6 +45,7 @@ func testExecutorCommandWithChroot(t *testing.T) *testExecCmd {
|
44 | 45 | "/etc/ld.so.cache": "/etc/ld.so.cache",
|
45 | 46 | "/etc/ld.so.conf": "/etc/ld.so.conf",
|
46 | 47 | "/etc/ld.so.conf.d": "/etc/ld.so.conf.d",
|
| 48 | + "/etc/passwd": "/etc/passwd", |
47 | 49 | "/lib": "/lib",
|
48 | 50 | "/lib64": "/lib64",
|
49 | 51 | "/usr/lib": "/usr/lib",
|
|
150 | 152 | /etc/:
|
151 | 153 | ld.so.cache
|
152 | 154 | ld.so.conf
|
153 |
| -ld.so.conf.d/` |
| 155 | +ld.so.conf.d/ |
| 156 | +passwd` |
154 | 157 | tu.WaitForResult(func() (bool, error) {
|
155 | 158 | output := testExecCmd.stdout.String()
|
156 | 159 | act := strings.TrimSpace(string(output))
|
@@ -239,6 +242,86 @@ func TestExecutor_EscapeContainer(t *testing.T) {
|
239 | 242 | require.NoError(err)
|
240 | 243 | }
|
241 | 244 |
|
| 245 | +func TestExecutor_Capabilities(t *testing.T) { |
| 246 | + t.Parallel() |
| 247 | + testutil.ExecCompatible(t) |
| 248 | + |
| 249 | + cases := []struct { |
| 250 | + user string |
| 251 | + caps string |
| 252 | + }{ |
| 253 | + { |
| 254 | + user: "nobody", |
| 255 | + caps: ` |
| 256 | +CapInh: 0000000000000000 |
| 257 | +CapPrm: 0000000000000000 |
| 258 | +CapEff: 0000000000000000 |
| 259 | +CapBnd: 0000003fffffffff |
| 260 | +CapAmb: 0000000000000000`, |
| 261 | + }, |
| 262 | + { |
| 263 | + user: "root", |
| 264 | + caps: ` |
| 265 | +CapInh: 0000000000000000 |
| 266 | +CapPrm: 0000003fffffffff |
| 267 | +CapEff: 0000003fffffffff |
| 268 | +CapBnd: 0000003fffffffff |
| 269 | +CapAmb: 0000000000000000`, |
| 270 | + }, |
| 271 | + } |
| 272 | + |
| 273 | + for _, c := range cases { |
| 274 | + t.Run(c.user, func(t *testing.T) { |
| 275 | + require := require.New(t) |
| 276 | + |
| 277 | + testExecCmd := testExecutorCommandWithChroot(t) |
| 278 | + execCmd, allocDir := testExecCmd.command, testExecCmd.allocDir |
| 279 | + defer allocDir.Destroy() |
| 280 | + |
| 281 | + execCmd.User = c.user |
| 282 | + execCmd.ResourceLimits = true |
| 283 | + execCmd.Cmd = "/bin/bash" |
| 284 | + execCmd.Args = []string{"-c", "cat /proc/$$/status"} |
| 285 | + |
| 286 | + executor := NewExecutorWithIsolation(testlog.HCLogger(t)) |
| 287 | + defer executor.Shutdown("SIGKILL", 0) |
| 288 | + |
| 289 | + _, err := executor.Launch(execCmd) |
| 290 | + require.NoError(err) |
| 291 | + |
| 292 | + ch := make(chan interface{}) |
| 293 | + go func() { |
| 294 | + executor.Wait(context.Background()) |
| 295 | + close(ch) |
| 296 | + }() |
| 297 | + |
| 298 | + select { |
| 299 | + case <-ch: |
| 300 | + // all good |
| 301 | + case <-time.After(5 * time.Second): |
| 302 | + require.Fail("timeout waiting for exec to shutdown") |
| 303 | + } |
| 304 | + |
| 305 | + canonical := func(s string) string { |
| 306 | + s = strings.TrimSpace(s) |
| 307 | + s = regexp.MustCompile("[ \t]+").ReplaceAllString(s, " ") |
| 308 | + s = regexp.MustCompile("[\n\r]+").ReplaceAllString(s, "\n") |
| 309 | + return s |
| 310 | + } |
| 311 | + |
| 312 | + expected := canonical(c.caps) |
| 313 | + tu.WaitForResult(func() (bool, error) { |
| 314 | + output := canonical(testExecCmd.stdout.String()) |
| 315 | + if !strings.Contains(output, expected) { |
| 316 | + return false, fmt.Errorf("capabilities didn't match: want\n%v\n; got:\n%v\n", expected, output) |
| 317 | + } |
| 318 | + return true, nil |
| 319 | + }, func(err error) { require.NoError(err) }) |
| 320 | + }) |
| 321 | + } |
| 322 | + |
| 323 | +} |
| 324 | + |
242 | 325 | func TestExecutor_ClientCleanup(t *testing.T) {
|
243 | 326 | t.Parallel()
|
244 | 327 | testutil.ExecCompatible(t)
|
|
0 commit comments