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  }