gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/runsc/cmd/capability_test.go (about) 1 // Copyright 2018 The gVisor 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 package cmd 16 17 import ( 18 "flag" 19 "fmt" 20 "os" 21 "slices" 22 "testing" 23 24 specs "github.com/opencontainers/runtime-spec/specs-go" 25 "github.com/syndtr/gocapability/capability" 26 "gvisor.dev/gvisor/pkg/log" 27 "gvisor.dev/gvisor/pkg/test/testutil" 28 "gvisor.dev/gvisor/runsc/config" 29 "gvisor.dev/gvisor/runsc/container" 30 "gvisor.dev/gvisor/runsc/specutils" 31 ) 32 33 func init() { 34 log.SetLevel(log.Debug) 35 if err := testutil.ConfigureExePath(); err != nil { 36 panic(err.Error()) 37 } 38 } 39 40 func checkProcessCaps(pid int, wantCaps *specs.LinuxCapabilities) error { 41 curCaps, err := capability.NewPid2(pid) 42 if err != nil { 43 return fmt.Errorf("capability.NewPid2(%d) failed: %v", pid, err) 44 } 45 if err := curCaps.Load(); err != nil { 46 return fmt.Errorf("unable to load capabilities: %v", err) 47 } 48 fmt.Printf("Capabilities (PID: %d): %v\n", pid, curCaps) 49 50 for _, c := range allCapTypes { 51 if err := checkCaps(c, curCaps, wantCaps); err != nil { 52 return err 53 } 54 } 55 return nil 56 } 57 58 func checkCaps(which capability.CapType, curCaps capability.Capabilities, wantCaps *specs.LinuxCapabilities) error { 59 wantNames := getCaps(which, wantCaps) 60 for name, c := range capFromName { 61 want := slices.Contains(wantNames, name) 62 got := curCaps.Get(which, c) 63 if want != got { 64 if want { 65 return fmt.Errorf("capability %v:%s should be set", which, name) 66 } 67 return fmt.Errorf("capability %v:%s should NOT be set", which, name) 68 } 69 } 70 return nil 71 } 72 73 func TestCapabilities(t *testing.T) { 74 t.Run("directfs", func(t *testing.T) { testCapabilities(t, true) }) 75 t.Run("lisafs", func(t *testing.T) { testCapabilities(t, false) }) 76 } 77 78 func testCapabilities(t *testing.T, directfs bool) { 79 stop := testutil.StartReaper() 80 defer stop() 81 82 spec := testutil.NewSpecWithArgs("/bin/sleep", "10000") 83 caps := []string{ 84 "CAP_CHOWN", 85 "CAP_SYS_PTRACE", // ptrace is added due to the platform choice. 86 } 87 spec.Process.Capabilities = &specs.LinuxCapabilities{ 88 Permitted: caps, 89 Bounding: caps, 90 Effective: caps, 91 Inheritable: caps, 92 } 93 94 conf := testutil.TestConfig(t) 95 conf.DirectFS = directfs 96 97 // Use --network=host to make sandbox use spec's capabilities. 98 conf.Network = config.NetworkHost 99 100 _, bundleDir, cleanup, err := testutil.SetupContainer(spec, conf) 101 if err != nil { 102 t.Fatalf("error setting up container: %v", err) 103 } 104 defer cleanup() 105 106 // Create and start the container. 107 args := container.Args{ 108 ID: testutil.RandomContainerID(), 109 Spec: spec, 110 BundleDir: bundleDir, 111 } 112 c, err := container.New(conf, args) 113 if err != nil { 114 t.Fatalf("error creating container: %v", err) 115 } 116 defer c.Destroy() 117 if err := c.Start(conf); err != nil { 118 t.Fatalf("error starting container: %v", err) 119 } 120 121 wantSandboxCaps := spec.Process.Capabilities 122 if directfs { 123 // With directfs, the sandbox has additional capabilities. 124 wantSandboxCaps = specutils.MergeCapabilities(wantSandboxCaps, directfsSandboxLinuxCaps) 125 } 126 // Check that sandbox and gofer have the proper capabilities. 127 if err := checkProcessCaps(c.Sandbox.Getpid(), wantSandboxCaps); err != nil { 128 t.Error(err) 129 } 130 if err := checkProcessCaps(c.GoferPid, goferCaps); err != nil { 131 t.Error(err) 132 } 133 } 134 135 func TestMain(m *testing.M) { 136 flag.Parse() 137 if err := specutils.MaybeRunAsRoot(); err != nil { 138 fmt.Fprintf(os.Stderr, "Error running as root: %v", err) 139 os.Exit(123) 140 } 141 os.Exit(m.Run()) 142 }