github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/mounts_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 fs_test
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/SagerNet/gvisor/pkg/context"
    21  	"github.com/SagerNet/gvisor/pkg/sentry/fs"
    22  	"github.com/SagerNet/gvisor/pkg/sentry/fs/fsutil"
    23  	"github.com/SagerNet/gvisor/pkg/sentry/fs/ramfs"
    24  	"github.com/SagerNet/gvisor/pkg/sentry/kernel/contexttest"
    25  )
    26  
    27  // Creates a new MountNamespace with filesystem:
    28  // /       (root dir)
    29  // |-foo   (dir)
    30  //   |-bar (file)
    31  func createMountNamespace(ctx context.Context) (*fs.MountNamespace, error) {
    32  	perms := fs.FilePermsFromMode(0777)
    33  	m := fs.NewPseudoMountSource(ctx)
    34  
    35  	barFile := fsutil.NewSimpleFileInode(ctx, fs.RootOwner, perms, 0)
    36  	fooDir := ramfs.NewDir(ctx, map[string]*fs.Inode{
    37  		"bar": fs.NewInode(ctx, barFile, m, fs.StableAttr{Type: fs.RegularFile}),
    38  	}, fs.RootOwner, perms)
    39  	rootDir := ramfs.NewDir(ctx, map[string]*fs.Inode{
    40  		"foo": fs.NewInode(ctx, fooDir, m, fs.StableAttr{Type: fs.Directory}),
    41  	}, fs.RootOwner, perms)
    42  
    43  	return fs.NewMountNamespace(ctx, fs.NewInode(ctx, rootDir, m, fs.StableAttr{Type: fs.Directory}))
    44  }
    45  
    46  func TestFindLink(t *testing.T) {
    47  	ctx := contexttest.Context(t)
    48  	mm, err := createMountNamespace(ctx)
    49  	if err != nil {
    50  		t.Fatalf("createMountNamespace failed: %v", err)
    51  	}
    52  
    53  	root := mm.Root()
    54  	defer root.DecRef(ctx)
    55  	foo, err := root.Walk(ctx, root, "foo")
    56  	if err != nil {
    57  		t.Fatalf("Error walking to foo: %v", err)
    58  	}
    59  
    60  	// Positive cases.
    61  	for _, tc := range []struct {
    62  		findPath string
    63  		wd       *fs.Dirent
    64  		wantPath string
    65  	}{
    66  		{".", root, "/"},
    67  		{".", foo, "/foo"},
    68  		{"..", foo, "/"},
    69  		{"../../..", foo, "/"},
    70  		{"///foo", foo, "/foo"},
    71  		{"/foo", foo, "/foo"},
    72  		{"/foo/bar", foo, "/foo/bar"},
    73  		{"/foo/.///./bar", foo, "/foo/bar"},
    74  		{"/foo///bar", foo, "/foo/bar"},
    75  		{"/foo/../foo/bar", foo, "/foo/bar"},
    76  		{"foo/bar", root, "/foo/bar"},
    77  		{"foo////bar", root, "/foo/bar"},
    78  		{"bar", foo, "/foo/bar"},
    79  	} {
    80  		wdPath, _ := tc.wd.FullName(root)
    81  		maxTraversals := uint(0)
    82  		if d, err := mm.FindLink(ctx, root, tc.wd, tc.findPath, &maxTraversals); err != nil {
    83  			t.Errorf("FindLink(%q, wd=%q) failed: %v", tc.findPath, wdPath, err)
    84  		} else if got, _ := d.FullName(root); got != tc.wantPath {
    85  			t.Errorf("FindLink(%q, wd=%q) got dirent %q, want %q", tc.findPath, wdPath, got, tc.wantPath)
    86  		}
    87  	}
    88  
    89  	// Negative cases.
    90  	for _, tc := range []struct {
    91  		findPath string
    92  		wd       *fs.Dirent
    93  	}{
    94  		{"bar", root},
    95  		{"/bar", root},
    96  		{"/foo/../../bar", root},
    97  		{"foo", foo},
    98  	} {
    99  		wdPath, _ := tc.wd.FullName(root)
   100  		maxTraversals := uint(0)
   101  		if _, err := mm.FindLink(ctx, root, tc.wd, tc.findPath, &maxTraversals); err == nil {
   102  			t.Errorf("FindLink(%q, wd=%q) did not return error", tc.findPath, wdPath)
   103  		}
   104  	}
   105  }