github.com/opencontainers/runtime-tools@v0.9.0/validation/linux_masked_paths/linux_masked_paths.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/mndrix/tap-go"
    10  	"github.com/opencontainers/runtime-tools/validation/util"
    11  	"golang.org/x/sys/unix"
    12  )
    13  
    14  func checkMaskedPaths(t *tap.T) error {
    15  	g, err := util.GetDefaultGenerator()
    16  	if err != nil {
    17  		return err
    18  	}
    19  
    20  	maskedDir := "masked-dir"
    21  	maskedSubDir := "masked-subdir"
    22  	maskedFile := "masked-file"
    23  
    24  	maskedDirTop := filepath.Join("/", maskedDir)
    25  	maskedFileTop := filepath.Join("/", maskedFile)
    26  
    27  	maskedDirSub := filepath.Join(maskedDirTop, maskedSubDir)
    28  	maskedFileSub := filepath.Join(maskedDirTop, maskedFile)
    29  	maskedFileSubSub := filepath.Join(maskedDirSub, maskedFile)
    30  
    31  	g.AddLinuxMaskedPaths(maskedDirTop)
    32  	g.AddLinuxMaskedPaths(maskedFileTop)
    33  	g.AddLinuxMaskedPaths(maskedDirSub)
    34  	g.AddLinuxMaskedPaths(maskedFileSub)
    35  	g.AddLinuxMaskedPaths(maskedFileSubSub)
    36  	g.AddAnnotation("TestName", "check masked paths")
    37  	err = util.RuntimeInsideValidate(g, t, func(path string) error {
    38  		testDir := filepath.Join(path, maskedDirSub)
    39  		err = os.MkdirAll(testDir, 0777)
    40  		if err != nil {
    41  			return err
    42  		}
    43  		// create a temp file to make testDir non-empty
    44  		tmpfile, err := ioutil.TempFile(testDir, "tmp")
    45  		if err != nil {
    46  			return err
    47  		}
    48  		defer os.Remove(tmpfile.Name())
    49  
    50  		// runtimetest cannot check the readability of empty files, so
    51  		// write something.
    52  		testSubSubFile := filepath.Join(path, maskedFileSubSub)
    53  		if err := ioutil.WriteFile(testSubSubFile, []byte("secrets"), 0777); err != nil {
    54  			return err
    55  		}
    56  
    57  		testSubFile := filepath.Join(path, maskedFileSub)
    58  		if err := ioutil.WriteFile(testSubFile, []byte("secrets"), 0777); err != nil {
    59  			return err
    60  		}
    61  
    62  		testFile := filepath.Join(path, maskedFile)
    63  		return ioutil.WriteFile(testFile, []byte("secrets"), 0777)
    64  	})
    65  	return err
    66  }
    67  
    68  func checkMaskedRelPaths(t *tap.T) error {
    69  	g, err := util.GetDefaultGenerator()
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	// Deliberately set a relative path to be masked, and expect an error
    75  	maskedRelPath := "masked-relpath"
    76  
    77  	g.AddLinuxMaskedPaths(maskedRelPath)
    78  	g.AddAnnotation("TestName", "check masked relative paths")
    79  	err = util.RuntimeInsideValidate(g, t, func(path string) error {
    80  		testFile := filepath.Join(path, maskedRelPath)
    81  		if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) {
    82  			return err
    83  		}
    84  
    85  		return nil
    86  	})
    87  	if err != nil {
    88  		return nil
    89  	}
    90  	return fmt.Errorf("expected: err != nil, actual: err == nil")
    91  }
    92  
    93  func checkMaskedSymlinks(t *tap.T) error {
    94  	g, err := util.GetDefaultGenerator()
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	// Deliberately create a masked symlink that points an invalid file,
   100  	// and expect an error.
   101  	maskedSymlink := "/masked-symlink"
   102  
   103  	g.AddLinuxMaskedPaths(maskedSymlink)
   104  	g.AddAnnotation("TestName", "check masked symlinks")
   105  	err = util.RuntimeInsideValidate(g, t, func(path string) error {
   106  		testFile := filepath.Join(path, maskedSymlink)
   107  		// ln -s .. /masked-symlink ; readlink -f /masked-symlink; ls -L /masked-symlink
   108  		if err := os.Symlink("../masked-symlink", testFile); err != nil {
   109  			return err
   110  		}
   111  		rPath, errR := os.Readlink(testFile)
   112  		if errR != nil {
   113  			return errR
   114  		}
   115  		_, errS := os.Stat(rPath)
   116  		if errS != nil && os.IsNotExist(errS) {
   117  			return errS
   118  		}
   119  
   120  		return nil
   121  	})
   122  	if err != nil {
   123  		return nil
   124  	}
   125  	return fmt.Errorf("expected: err != nil, actual: err == nil")
   126  }
   127  
   128  func checkMaskedDeviceNodes(t *tap.T, mode uint32) error {
   129  	g, err := util.GetDefaultGenerator()
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	maskedDevice := "/masked-device"
   135  
   136  	g.AddLinuxMaskedPaths(maskedDevice)
   137  	g.AddAnnotation("TestName", "check masked device nodes")
   138  	return util.RuntimeInsideValidate(g, t, func(path string) error {
   139  		testFile := filepath.Join(path, maskedDevice)
   140  
   141  		if err := unix.Mknod(testFile, mode, 0); err != nil {
   142  			return err
   143  		}
   144  
   145  		if _, err := os.Stat(testFile); err != nil && os.IsNotExist(err) {
   146  			return err
   147  		}
   148  
   149  		return nil
   150  	})
   151  }
   152  
   153  func main() {
   154  	t := tap.New()
   155  	t.Header(0)
   156  	defer t.AutoPlan()
   157  
   158  	if err := checkMaskedPaths(t); err != nil {
   159  		util.Fatal(err)
   160  	}
   161  
   162  	if err := checkMaskedRelPaths(t); err != nil {
   163  		util.Fatal(err)
   164  	}
   165  
   166  	if err := checkMaskedSymlinks(t); err != nil {
   167  		util.Fatal(err)
   168  	}
   169  
   170  	// test creation of different type of devices, i.e. block device,
   171  	// character device, and FIFO.
   172  	modes := []uint32{
   173  		unix.S_IFBLK | 0666,
   174  		unix.S_IFCHR | 0666,
   175  		unix.S_IFIFO | 0666,
   176  	}
   177  
   178  	for _, m := range modes {
   179  		if err := checkMaskedDeviceNodes(t, m); err != nil {
   180  			util.Fatal(err)
   181  		}
   182  	}
   183  }