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 }