github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/rkt_caps_test.go (about) 1 // Copyright 2015 The rkt Authors 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 15 // +build host coreos src kvm 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "strings" 23 "testing" 24 25 "github.com/rkt/rkt/common" 26 "github.com/rkt/rkt/tests/testutils" 27 "github.com/syndtr/gocapability/capability" 28 ) 29 30 var appCapsTests = []struct { 31 // constants 32 testName string // name of the image 33 capRetainSet string // only use value if != "x" 34 capRemoveSet string // only use value if != "x" 35 expected string // caps bounding set as printed by gocapability 36 useOldFlag bool // use --cap-retain or --cap-remove instead of --caps-*; backwards compatibility testing 37 38 // set during the test 39 imageFile string 40 }{ 41 // Testing without isolators 42 { 43 testName: "image-none", 44 capRetainSet: "x", 45 capRemoveSet: "x", 46 expected: strings.Join([]string{ 47 "chown", 48 "dac_override", 49 "fowner", 50 "fsetid", 51 "kill", 52 "setgid", 53 "setuid", 54 "setpcap", 55 "net_bind_service", 56 "net_raw", 57 "sys_chroot", 58 "mknod", 59 "audit_write", 60 "setfcap", 61 }, ", "), 62 }, 63 // Testing retain set 64 { 65 testName: "image-only-one-cap", 66 capRetainSet: "CAP_NET_ADMIN", 67 capRemoveSet: "x", 68 expected: "net_admin", 69 }, 70 { 71 testName: "image-only-one-cap-old", 72 capRetainSet: "CAP_NET_ADMIN", 73 capRemoveSet: "x", 74 expected: "net_admin", 75 useOldFlag: true, 76 }, 77 { 78 testName: "image-only-one-cap-from-default", 79 capRetainSet: "CAP_CHOWN", 80 capRemoveSet: "x", 81 expected: "chown", 82 }, 83 { 84 testName: "image-some-caps", 85 capRetainSet: strings.Join([]string{ 86 "CAP_CHOWN", 87 "CAP_FOWNER", 88 "CAP_SYS_ADMIN", 89 "CAP_NET_ADMIN", 90 }, ","), 91 capRemoveSet: "x", 92 expected: strings.Join([]string{ 93 "chown", 94 "fowner", 95 "net_admin", 96 "sys_admin", 97 }, ", "), 98 }, 99 { 100 testName: "image-caps-from-nspawn-default", 101 capRetainSet: strings.Join([]string{ 102 "CAP_CHOWN", 103 "CAP_DAC_OVERRIDE", 104 "CAP_DAC_READ_SEARCH", 105 "CAP_FOWNER", 106 "CAP_FSETID", 107 "CAP_IPC_OWNER", 108 "CAP_KILL", 109 "CAP_LEASE", 110 "CAP_LINUX_IMMUTABLE", 111 "CAP_NET_BIND_SERVICE", 112 "CAP_NET_BROADCAST", 113 "CAP_NET_RAW", 114 "CAP_SETGID", 115 "CAP_SETFCAP", 116 "CAP_SETPCAP", 117 "CAP_SETUID", 118 "CAP_SYS_ADMIN", 119 "CAP_SYS_CHROOT", 120 "CAP_SYS_NICE", 121 "CAP_SYS_PTRACE", 122 "CAP_SYS_TTY_CONFIG", 123 "CAP_SYS_RESOURCE", 124 "CAP_SYS_BOOT", 125 "CAP_AUDIT_WRITE", 126 "CAP_AUDIT_CONTROL", 127 }, ","), 128 capRemoveSet: "x", 129 expected: strings.Join([]string{ 130 "chown", 131 "dac_override", 132 "dac_read_search", 133 "fowner", 134 "fsetid", 135 "kill", 136 "setgid", 137 "setuid", 138 "setpcap", 139 "linux_immutable", 140 "net_bind_service", 141 "net_broadcast", 142 "net_raw", 143 "ipc_owner", 144 "sys_chroot", 145 "sys_ptrace", 146 "sys_admin", 147 "sys_boot", 148 "sys_nice", 149 "sys_resource", 150 "sys_tty_config", 151 "lease", 152 "audit_write", 153 "audit_control", 154 "setfcap", 155 }, ", "), 156 }, 157 // Testing remove set 158 { 159 testName: "image-remove-one-from-default", 160 capRetainSet: "x", 161 capRemoveSet: "CAP_CHOWN", 162 expected: strings.Join([]string{ 163 "dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap", 164 }, ", "), 165 }, 166 { 167 testName: "image-remove-one-from-default-old", 168 capRetainSet: "x", 169 capRemoveSet: "CAP_CHOWN", 170 useOldFlag: true, 171 expected: strings.Join([]string{ 172 "dac_override, fowner, fsetid, kill, setgid, setuid, setpcap, net_bind_service, net_raw, sys_chroot, mknod, audit_write, setfcap", 173 }, ", "), 174 }, 175 { 176 testName: "image-remove-one-already-removed", 177 capRetainSet: "x", 178 capRemoveSet: "CAP_SYS_ADMIN", 179 expected: strings.Join([]string{ 180 "chown", 181 "dac_override", 182 "fowner", 183 "fsetid", 184 "kill", 185 "setgid", 186 "setuid", 187 "setpcap", 188 "net_bind_service", 189 "net_raw", 190 "sys_chroot", 191 "mknod", 192 "audit_write", 193 "setfcap", 194 }, ", "), 195 }, 196 { 197 testName: "image-remove-two", 198 capRetainSet: "x", 199 capRemoveSet: "CAP_CHOWN,CAP_SYS_ADMIN", 200 expected: strings.Join([]string{ 201 "dac_override", 202 "fowner", 203 "fsetid", 204 "kill", 205 "setgid", 206 "setuid", 207 "setpcap", 208 "net_bind_service", 209 "net_raw", 210 "sys_chroot", 211 "mknod", 212 "audit_write", 213 "setfcap", 214 }, ", "), 215 }, 216 { 217 testName: "image-remove-all", 218 capRetainSet: "x", 219 capRemoveSet: strings.Join([]string{ 220 "CAP_AUDIT_WRITE", 221 "CAP_CHOWN", 222 "CAP_DAC_OVERRIDE", 223 "CAP_FSETID", 224 "CAP_FOWNER", 225 "CAP_KILL", 226 "CAP_MKNOD", 227 "CAP_NET_RAW", 228 "CAP_NET_BIND_SERVICE", 229 "CAP_SETUID", 230 "CAP_SETGID", 231 "CAP_SETPCAP", 232 "CAP_SETFCAP", 233 "CAP_SYS_CHROOT", 234 }, ","), 235 expected: "", 236 }, 237 { 238 testName: "image-remove-all-but-one", 239 capRetainSet: "x", 240 capRemoveSet: strings.Join([]string{ 241 "CAP_AUDIT_WRITE", 242 "CAP_CHOWN", 243 "CAP_DAC_OVERRIDE", 244 "CAP_FSETID", 245 "CAP_FOWNER", 246 "CAP_KILL", 247 "CAP_MKNOD", 248 "CAP_NET_RAW", 249 "CAP_NET_BIND_SERVICE", 250 "CAP_SETUID", 251 "CAP_SETGID", 252 "CAP_SETPCAP", 253 "CAP_SETFCAP", 254 }, ","), 255 expected: "sys_chroot", 256 }, 257 { 258 testName: "image-remove-all-plus-one", 259 capRetainSet: "x", 260 capRemoveSet: strings.Join([]string{ 261 "CAP_AUDIT_WRITE", 262 "CAP_CHOWN", 263 "CAP_DAC_OVERRIDE", 264 "CAP_FSETID", 265 "CAP_FOWNER", 266 "CAP_KILL", 267 "CAP_MKNOD", 268 "CAP_NET_RAW", 269 "CAP_NET_BIND_SERVICE", 270 "CAP_SETUID", 271 "CAP_SETGID", 272 "CAP_SETPCAP", 273 "CAP_SETFCAP", 274 "CAP_SYS_CHROOT", 275 "CAP_SYS_ADMIN", 276 }, ","), 277 expected: "", 278 }, 279 // Testing with an empty retain set or an empty remove set 280 // TODO(alban): "actool patch-manifest" cannot generate those images for now 281 //{ 282 // testName: "image-retain-set-empty", 283 // capRetainSet: "", 284 // capRemoveSet: "x", 285 // expected: "", 286 //}, 287 //{ 288 // testName: "image-remove-none", 289 // capRetainSet: "x", 290 // capRemoveSet: "", 291 // expected: "TODO(alban)", 292 //}, 293 } 294 295 func capsSeveralAppsRunAndCheckOutput(t *testing.T, ctx *testutils.RktRunCtx, cmd string) { 296 // Ideally, the test would run the pod only one time, but all 297 // apps' output is mixed together without ordering guarantees, so 298 // it makes it impossible to call all the expectWithOutput() in 299 // the correct order. 300 for _, tt := range appCapsTests { 301 t.Logf("Checking caps for %q", tt.testName) 302 child := spawnOrFail(t, cmd) 303 304 expected := fmt.Sprintf("Capability set: bounding: %s (%s)", 305 tt.expected, tt.testName) 306 if err := expectWithOutput(child, expected); err != nil { 307 t.Fatalf("Expected %q but not found: %v", expected, err) 308 } 309 310 waitOrFail(t, child, 0) 311 312 ctx.RunGC() 313 } 314 } 315 316 func TestCapsSeveralAppWithPatches(t *testing.T) { 317 if err := common.SupportsOverlay(); err != nil { 318 t.Skipf("Skipping storage-intensive test, overlayfs not supported: %v", err) 319 } 320 321 // All the following images are launched together in the same pod 322 323 ctx := testutils.NewRktRunCtx() 324 defer ctx.Cleanup() 325 326 for i, tt := range appCapsTests { 327 patches := []string{ 328 fmt.Sprintf("--name=%s", tt.testName), 329 fmt.Sprintf("--exec=/inspect --print-caps-pid=0 --suffix-msg=%s", tt.testName), 330 } 331 if tt.capRetainSet != "x" { 332 patches = append(patches, "--capability="+tt.capRetainSet) 333 } 334 if tt.capRemoveSet != "x" { 335 patches = append(patches, "--revoke-capability="+tt.capRemoveSet) 336 } 337 imageFile := patchTestACI(tt.testName+".aci", patches...) 338 defer os.Remove(imageFile) 339 appCapsTests[i].imageFile = imageFile 340 t.Logf("Built image %q", imageFile) 341 } 342 343 // Generate the rkt arguments to launch all the apps in the same pod 344 rktArgs := "" 345 for _, tt := range appCapsTests { 346 rktArgs += " " + tt.imageFile 347 } 348 cmd := fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), rktArgs) 349 350 capsSeveralAppsRunAndCheckOutput(t, ctx, cmd) 351 } 352 353 func TestCapsSeveralAppWithFlags(t *testing.T) { 354 if err := common.SupportsOverlay(); err != nil { 355 t.Skipf("Skipping storage-intensive test, overlayfs not supported: %v", err) 356 } 357 358 // All the following images are launched together in the same pod 359 ctx := testutils.NewRktRunCtx() 360 defer ctx.Cleanup() 361 362 for i, tt := range appCapsTests { 363 imageFile := patchTestACI(tt.testName+".aci", fmt.Sprintf("--name=%s", tt.testName), 364 fmt.Sprintf("--exec=/inspect --print-caps-pid=0 --suffix-msg=%s", tt.testName)) 365 defer os.Remove(imageFile) 366 appCapsTests[i].imageFile = imageFile 367 t.Logf("Built image %q", imageFile) 368 } 369 370 // Generate the rkt arguments to launch all the apps in the same pod 371 rktArgs := "" 372 for _, tt := range appCapsTests { 373 rktArgs += " " + tt.imageFile 374 if tt.capRetainSet != "x" { 375 capFlag := " --caps-retain" 376 if tt.useOldFlag { 377 capFlag = " --cap-retain" 378 } 379 rktArgs += fmt.Sprintf("%s=%s", capFlag, tt.capRetainSet) 380 } 381 if tt.capRemoveSet != "x" { 382 capFlag := " --caps-remove" 383 if tt.useOldFlag { 384 capFlag = " --cap-remove" 385 } 386 rktArgs += fmt.Sprintf("%s=%s", capFlag, tt.capRemoveSet) 387 } 388 } 389 cmd := fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), rktArgs) 390 391 capsSeveralAppsRunAndCheckOutput(t, ctx, cmd) 392 } 393 394 // Tests that flags on the command line override the isolator in the ACI 395 func TestCapsOverride(t *testing.T) { 396 if err := common.SupportsOverlay(); err != nil { 397 t.Skipf("Skipping storage-intensive test, overlayfs not supported: %v", err) 398 } 399 400 ctx := testutils.NewRktRunCtx() 401 defer ctx.Cleanup() 402 403 var appCapsOverride = []struct { 404 testName string // name of the image 405 capRetainSetImg string // only use value if != "x" 406 capRemoveSetImg string // only use value if != "x" 407 capRetainSetFlg string // only use value if != "x" 408 capRemoveSetFlg string // only use value if != "x" 409 expected string // caps bounding set as printed by gocapability 410 }{ 411 { 412 testName: "retain-override-retain", 413 capRetainSetImg: "CAP_MKNOD", 414 capRemoveSetImg: "x", 415 capRetainSetFlg: "CAP_SYS_ADMIN", 416 capRemoveSetFlg: "x", 417 expected: strings.Join([]string{ 418 "sys_admin", 419 }, ", "), 420 }, 421 { 422 testName: "retain-override-remove", 423 capRetainSetImg: "x", 424 capRemoveSetImg: "CAP_CHOWN", 425 capRetainSetFlg: "CAP_SYS_ADMIN", 426 capRemoveSetFlg: "x", 427 expected: strings.Join([]string{ 428 "sys_admin", 429 }, ", "), 430 }, 431 { 432 testName: "remove-override-remove", 433 capRetainSetImg: "x", 434 capRemoveSetImg: "CAP_CHOWN", 435 capRetainSetFlg: "x", 436 capRemoveSetFlg: "CAP_KILL", 437 expected: strings.Join([]string{ 438 "chown", 439 "dac_override", 440 "fowner", 441 "fsetid", 442 "setgid", 443 "setuid", 444 "setpcap", 445 "net_bind_service", 446 "net_raw", 447 "sys_chroot", 448 "mknod", 449 "audit_write", 450 "setfcap", 451 }, ", "), 452 }, 453 { 454 testName: "remove-override-retain", 455 capRetainSetImg: "CAP_MKNOD", 456 capRemoveSetImg: "x", 457 capRetainSetFlg: "x", 458 capRemoveSetFlg: "CAP_KILL", 459 expected: strings.Join([]string{ 460 "chown", 461 "dac_override", 462 "fowner", 463 "fsetid", 464 "setgid", 465 "setuid", 466 "setpcap", 467 "net_bind_service", 468 "net_raw", 469 "sys_chroot", 470 "mknod", 471 "audit_write", 472 "setfcap", 473 }, ", "), 474 }, 475 } 476 477 for _, tt := range appCapsOverride { 478 patches := []string{ 479 fmt.Sprintf("--name=%s", tt.testName), 480 fmt.Sprintf("--exec=/inspect --print-caps-pid=0 --suffix-msg=%s", tt.testName), 481 } 482 if tt.capRetainSetImg != "x" { 483 patches = append(patches, "--capability="+tt.capRetainSetImg) 484 } 485 if tt.capRemoveSetImg != "x" { 486 patches = append(patches, "--revoke-capability="+tt.capRemoveSetImg) 487 } 488 imageFile := patchTestACI(tt.testName+".aci", patches...) 489 defer os.Remove(imageFile) 490 t.Logf("Built image %q", imageFile) 491 492 cmd := fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), imageFile) 493 if tt.capRetainSetFlg != "x" { 494 cmd += " --cap-retain=" + tt.capRetainSetFlg 495 } 496 if tt.capRemoveSetFlg != "x" { 497 cmd += " --cap-remove=" + tt.capRemoveSetFlg 498 } 499 500 t.Logf("Checking caps for %q", tt.testName) 501 child := spawnOrFail(t, cmd) 502 503 expected := fmt.Sprintf("Capability set: bounding: %s (%s)", 504 tt.expected, tt.testName) 505 if err := expectWithOutput(child, expected); err != nil { 506 t.Fatalf("Expected %q but not found: %v", expected, err) 507 } 508 509 waitOrFail(t, child, 0) 510 511 ctx.RunGC() 512 } 513 } 514 515 // Tests that --insecure-options=capabilities allows everything 516 func TestCapsInsecureOption(t *testing.T) { 517 if err := common.SupportsOverlay(); err != nil { 518 t.Skipf("Skipping storage-intensive test, overlayfs not supported: %v", err) 519 } 520 521 ctx := testutils.NewRktRunCtx() 522 defer ctx.Cleanup() 523 524 imageFile := patchTestACI("insecure-options-caps.aci", "--exec=/inspect --print-caps-pid=0") 525 defer os.Remove(imageFile) 526 527 defaultCaps := strings.Join([]string{ 528 "chown", 529 "dac_override", 530 "fowner", 531 "fsetid", 532 "kill", 533 "setgid", 534 "setuid", 535 "setpcap", 536 "net_bind_service", 537 "net_raw", 538 "sys_chroot", 539 "mknod", 540 "audit_write", 541 "setfcap", 542 }, ", ") 543 544 // All capabilities defined in Linux, in the same order as their definition: 545 // https://github.com/torvalds/linux/blob/v4.7/include/uapi/linux/capability.h#L90 546 allCaps := strings.Join([]string{ 547 "chown", 548 "dac_override", 549 "dac_read_search", 550 "fowner", 551 "fsetid", 552 "kill", 553 "setgid", 554 "setuid", 555 "setpcap", 556 "linux_immutable", 557 "net_bind_service", 558 "net_broadcast", 559 "net_admin", 560 "net_raw", 561 "ipc_lock", 562 "ipc_owner", 563 "sys_module", 564 "sys_rawio", 565 "sys_chroot", 566 "sys_ptrace", 567 "sys_pacct", 568 "sys_admin", 569 "sys_boot", 570 "sys_nice", 571 "sys_resource", 572 "sys_time", 573 "sys_tty_config", 574 "mknod", 575 "lease", 576 "audit_write", 577 "audit_control", 578 "setfcap", 579 "mac_override", 580 "mac_admin", 581 "syslog", 582 "wake_alarm", 583 "block_suspend", 584 // do not check "audit_read" to support tests in older kernels 585 // "audit_read", // since Linux 3.16 586 }, ", ") 587 588 // Without --insecure-options=capabilities 589 expectedDefault := fmt.Sprintf("Capability set: bounding: %s", defaultCaps) 590 for _, insecureOption := range []string{"image", "image,ondisk,paths", "all-fetch"} { 591 // run 592 t.Logf("run: check caps with --insecure-options=%s\n", insecureOption) 593 cmd := fmt.Sprintf(`%s --debug --insecure-options=%s run %s`, ctx.Cmd(), insecureOption, imageFile) 594 runRktAndCheckOutput(t, cmd, expectedDefault, false) 595 // run-prepared 596 t.Logf("run-prepared: check caps with --insecure-options=%s\n", insecureOption) 597 cmd = fmt.Sprintf(`%s --insecure-options=%s prepare %s`, ctx.Cmd(), insecureOption, imageFile) 598 uuid := runRktAndGetUUID(t, cmd) 599 cmd = fmt.Sprintf("%s --insecure-options=%s --debug run-prepared %s", ctx.Cmd(), insecureOption, uuid) 600 runRktAndCheckOutput(t, cmd, expectedDefault, false) 601 } 602 603 // With --insecure-options=capabilities 604 expectedAll := fmt.Sprintf("Capability set: bounding: %s", allCaps) 605 for _, insecureOption := range []string{"image,capabilities", "image,ondisk,paths,capabilities", "all-fetch,capabilities", "all"} { 606 // run 607 t.Logf("run: check caps with --insecure-options=%s\n", insecureOption) 608 cmd := fmt.Sprintf(`%s --debug --insecure-options=%s run %s`, ctx.Cmd(), insecureOption, imageFile) 609 runRktAndCheckOutput(t, cmd, expectedAll, false) 610 // run-prepared 611 t.Logf("run-prepared: check caps with --insecure-options=%s\n", insecureOption) 612 cmd = fmt.Sprintf(`%s --insecure-options=%s prepare %s`, ctx.Cmd(), insecureOption, imageFile) 613 uuid := runRktAndGetUUID(t, cmd) 614 cmd = fmt.Sprintf("%s --insecure-options=%s --debug run-prepared %s", ctx.Cmd(), insecureOption, uuid) 615 runRktAndCheckOutput(t, cmd, expectedAll, false) 616 } 617 } 618 619 var capsTests = []struct { 620 testName string 621 capIsolator string 622 capa capability.Cap 623 capInStage1Expected bool 624 capInStage2Expected bool 625 nonrootCapExpected bool 626 }{ 627 { 628 testName: "Check we don't have CAP_NET_ADMIN without isolator", 629 capIsolator: "", 630 capa: capability.CAP_NET_ADMIN, 631 capInStage1Expected: false, 632 capInStage2Expected: false, 633 nonrootCapExpected: false, 634 }, 635 { 636 testName: "Check we have CAP_MKNOD without isolator", 637 capIsolator: "", 638 capa: capability.CAP_MKNOD, 639 capInStage1Expected: true, 640 capInStage2Expected: true, 641 nonrootCapExpected: true, 642 }, 643 { 644 testName: "Check we have CAP_NET_ADMIN with an isolator", 645 capIsolator: "CAP_NET_ADMIN,CAP_NET_BIND_SERVICE", 646 capa: capability.CAP_NET_ADMIN, 647 capInStage1Expected: true, 648 capInStage2Expected: true, 649 nonrootCapExpected: true, 650 }, 651 { 652 testName: "Check we have CAP_NET_BIND_SERVICE with an isolator", 653 capIsolator: "CAP_NET_ADMIN,CAP_NET_BIND_SERVICE", 654 capa: capability.CAP_NET_BIND_SERVICE, 655 capInStage1Expected: true, 656 capInStage2Expected: true, 657 nonrootCapExpected: true, 658 }, 659 { 660 testName: "Check we don't have CAP_NET_ADMIN with an isolator setting CAP_NET_BIND_SERVICE", 661 capIsolator: "CAP_NET_BIND_SERVICE", 662 capa: capability.CAP_NET_ADMIN, 663 capInStage1Expected: false, 664 capInStage2Expected: false, 665 nonrootCapExpected: false, 666 }, 667 } 668 669 func NewCapsTest(hasStage1FullCaps bool) testutils.Test { 670 return testutils.TestFunc(func(t *testing.T) { 671 ctx := testutils.NewRktRunCtx() 672 defer ctx.Cleanup() 673 674 for i, tt := range capsTests { 675 stage1Args := []string{"--exec=/inspect --print-caps-pid=1 --print-user"} 676 stage2Args := []string{"--exec=/inspect --print-caps-pid=0 --print-user"} 677 if tt.capIsolator != "" { 678 stage1Args = append(stage1Args, "--capability="+tt.capIsolator) 679 stage2Args = append(stage2Args, "--capability="+tt.capIsolator) 680 } 681 stage1FileName := patchTestACI("rkt-inspect-print-caps-stage1.aci", stage1Args...) 682 defer os.Remove(stage1FileName) 683 stage2FileName := patchTestACI("rkt-inspect-print-caps-stage2.aci", stage2Args...) 684 defer os.Remove(stage2FileName) 685 stageFileNames := []string{stage1FileName, stage2FileName} 686 687 for _, stage := range []int{1, 2} { 688 t.Logf("Running test #%v: %v [stage%v]", i, tt.testName, stage) 689 690 cmd := fmt.Sprintf("%s --debug --insecure-options=image run --mds-register=false --set-env=CAPABILITY=%d %s", ctx.Cmd(), int(tt.capa), stageFileNames[stage-1]) 691 child := spawnOrFail(t, cmd) 692 693 expectedLine := tt.capa.String() 694 695 capInStage1Expected := tt.capInStage1Expected || hasStage1FullCaps 696 697 if (stage == 1 && capInStage1Expected) || (stage == 2 && tt.capInStage2Expected) { 698 expectedLine += "=enabled" 699 } else { 700 expectedLine += "=disabled" 701 } 702 703 if err := expectWithOutput(child, expectedLine); err != nil { 704 t.Fatalf("Expected %q but not found: %v", expectedLine, err) 705 } 706 707 if err := expectWithOutput(child, "User: uid=0 euid=0 gid=0 egid=0"); err != nil { 708 t.Fatalf("Expected user 0 but not found: %v", err) 709 } 710 711 waitOrFail(t, child, 0) 712 } 713 ctx.Reset() 714 } 715 }) 716 } 717 718 func TestCapsNonRoot(t *testing.T) { 719 if err := common.SupportsOverlay(); err != nil { 720 t.Skipf("Skipping storage-intensive test, overlayfs not supported: %v", err) 721 } 722 723 ctx := testutils.NewRktRunCtx() 724 defer ctx.Cleanup() 725 726 for i, tt := range capsTests { 727 args := []string{"--exec=/inspect --print-caps-pid=0 --print-user", "--user=9000", "--group=9000"} 728 if tt.capIsolator != "" { 729 args = append(args, "--capability="+tt.capIsolator) 730 } 731 fileName := patchTestACI("rkt-inspect-print-caps-nonroot.aci", args...) 732 defer os.Remove(fileName) 733 734 t.Logf("Running test #%v: %v [non-root]", i, tt.testName) 735 736 cmd := fmt.Sprintf("%s --debug --insecure-options=image run --mds-register=false --set-env=CAPABILITY=%d %s", ctx.Cmd(), int(tt.capa), fileName) 737 child := spawnOrFail(t, cmd) 738 739 expectedLine := tt.capa.String() 740 if tt.nonrootCapExpected { 741 expectedLine += "=enabled" 742 } else { 743 expectedLine += "=disabled" 744 } 745 if err := expectWithOutput(child, expectedLine); err != nil { 746 t.Fatalf("Expected %q but not found: %v", expectedLine, err) 747 } 748 749 if err := expectWithOutput(child, "User: uid=9000 euid=9000 gid=9000 egid=9000"); err != nil { 750 t.Fatalf("Expected user 9000 but not found: %v", err) 751 } 752 753 waitOrFail(t, child, 0) 754 ctx.Reset() 755 } 756 }