github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/kernfs/synthetic_directory.go (about) 1 // Copyright 2019 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 kernfs 16 17 import ( 18 "fmt" 19 20 "github.com/SagerNet/gvisor/pkg/abi/linux" 21 "github.com/SagerNet/gvisor/pkg/context" 22 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 23 "github.com/SagerNet/gvisor/pkg/sentry/kernel/auth" 24 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 25 ) 26 27 // syntheticDirectory implements kernfs.Inode for a directory created by 28 // MkdirAt(ForSyntheticMountpoint=true). 29 // 30 // +stateify savable 31 type syntheticDirectory struct { 32 InodeAlwaysValid 33 InodeAttrs 34 InodeNoStatFS 35 InodeNotSymlink 36 OrderedChildren 37 syntheticDirectoryRefs 38 39 locks vfs.FileLocks 40 } 41 42 var _ Inode = (*syntheticDirectory)(nil) 43 44 func newSyntheticDirectory(ctx context.Context, creds *auth.Credentials, perm linux.FileMode) Inode { 45 if perm&^linux.PermissionsMask != 0 { 46 panic(fmt.Sprintf("perm contains non-permission bits: %#o", perm)) 47 } 48 dir := &syntheticDirectory{} 49 dir.InitRefs() 50 dir.InodeAttrs.Init(ctx, creds, 0 /* devMajor */, 0 /* devMinor */, 0 /* ino */, linux.S_IFDIR|perm) 51 dir.OrderedChildren.Init(OrderedChildrenOptions{ 52 Writable: true, 53 }) 54 return dir 55 } 56 57 // Open implements Inode.Open. 58 func (dir *syntheticDirectory) Open(ctx context.Context, rp *vfs.ResolvingPath, d *Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) { 59 fd, err := NewGenericDirectoryFD(rp.Mount(), d, &dir.OrderedChildren, &dir.locks, &opts, GenericDirectoryFDOptions{}) 60 if err != nil { 61 return nil, err 62 } 63 return &fd.vfsfd, nil 64 } 65 66 // NewFile implements Inode.NewFile. 67 func (dir *syntheticDirectory) NewFile(ctx context.Context, name string, opts vfs.OpenOptions) (Inode, error) { 68 return nil, linuxerr.EPERM 69 } 70 71 // NewDir implements Inode.NewDir. 72 func (dir *syntheticDirectory) NewDir(ctx context.Context, name string, opts vfs.MkdirOptions) (Inode, error) { 73 if !opts.ForSyntheticMountpoint { 74 return nil, linuxerr.EPERM 75 } 76 subdirI := newSyntheticDirectory(ctx, auth.CredentialsFromContext(ctx), opts.Mode&linux.PermissionsMask) 77 if err := dir.OrderedChildren.Insert(name, subdirI); err != nil { 78 subdirI.DecRef(ctx) 79 return nil, err 80 } 81 dir.TouchCMtime(ctx) 82 return subdirI, nil 83 } 84 85 // NewLink implements Inode.NewLink. 86 func (dir *syntheticDirectory) NewLink(ctx context.Context, name string, target Inode) (Inode, error) { 87 return nil, linuxerr.EPERM 88 } 89 90 // NewSymlink implements Inode.NewSymlink. 91 func (dir *syntheticDirectory) NewSymlink(ctx context.Context, name, target string) (Inode, error) { 92 return nil, linuxerr.EPERM 93 } 94 95 // NewNode implements Inode.NewNode. 96 func (dir *syntheticDirectory) NewNode(ctx context.Context, name string, opts vfs.MknodOptions) (Inode, error) { 97 return nil, linuxerr.EPERM 98 } 99 100 // DecRef implements Inode.DecRef. 101 func (dir *syntheticDirectory) DecRef(ctx context.Context) { 102 dir.syntheticDirectoryRefs.DecRef(func() { dir.Destroy(ctx) }) 103 } 104 105 // Keep implements Inode.Keep. This is redundant because inodes will never be 106 // created via Lookup and inodes are always valid. Makes sense to return true 107 // because these inodes are not temporary and should only be removed on RmDir. 108 func (dir *syntheticDirectory) Keep() bool { 109 return true 110 }