github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fs/ramfs/symlink.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 ramfs 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/abi/linux" 19 "github.com/SagerNet/gvisor/pkg/context" 20 "github.com/SagerNet/gvisor/pkg/sentry/fs" 21 "github.com/SagerNet/gvisor/pkg/sentry/fs/fsutil" 22 "github.com/SagerNet/gvisor/pkg/waiter" 23 ) 24 25 // Symlink represents a symlink. 26 // 27 // +stateify savable 28 type Symlink struct { 29 fsutil.InodeGenericChecker `state:"nosave"` 30 fsutil.InodeNoopRelease `state:"nosave"` 31 fsutil.InodeNoopWriteOut `state:"nosave"` 32 fsutil.InodeNotAllocatable `state:"nosave"` 33 fsutil.InodeNotDirectory `state:"nosave"` 34 fsutil.InodeNotMappable `state:"nosave"` 35 fsutil.InodeNotSocket `state:"nosave"` 36 fsutil.InodeNotTruncatable `state:"nosave"` 37 fsutil.InodeVirtual `state:"nosave"` 38 39 fsutil.InodeSimpleAttributes 40 fsutil.InodeSimpleExtendedAttributes 41 42 // Target is the symlink target. 43 Target string 44 } 45 46 var _ fs.InodeOperations = (*Symlink)(nil) 47 48 // NewSymlink returns a new Symlink. 49 func NewSymlink(ctx context.Context, owner fs.FileOwner, target string) *Symlink { 50 // A symlink is assumed to always have permissions 0777. 51 return &Symlink{ 52 InodeSimpleAttributes: fsutil.NewInodeSimpleAttributes(ctx, owner, fs.FilePermsFromMode(0777), linux.RAMFS_MAGIC), 53 Target: target, 54 } 55 } 56 57 // UnstableAttr returns all attributes of this ramfs symlink. 58 func (s *Symlink) UnstableAttr(ctx context.Context, inode *fs.Inode) (fs.UnstableAttr, error) { 59 uattr, err := s.InodeSimpleAttributes.UnstableAttr(ctx, inode) 60 if err != nil { 61 return fs.UnstableAttr{}, err 62 } 63 uattr.Size = int64(len(s.Target)) 64 uattr.Usage = uattr.Size 65 return uattr, nil 66 } 67 68 // SetPermissions on a symlink is always rejected. 69 func (s *Symlink) SetPermissions(context.Context, *fs.Inode, fs.FilePermissions) bool { 70 return false 71 } 72 73 // Readlink reads the symlink value. 74 func (s *Symlink) Readlink(ctx context.Context, _ *fs.Inode) (string, error) { 75 s.NotifyAccess(ctx) 76 return s.Target, nil 77 } 78 79 // Getlink returns ErrResolveViaReadlink, falling back to walking to the result 80 // of Readlink(). 81 func (*Symlink) Getlink(context.Context, *fs.Inode) (*fs.Dirent, error) { 82 return nil, fs.ErrResolveViaReadlink 83 } 84 85 // GetFile implements fs.FileOperations.GetFile. 86 func (s *Symlink) GetFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags) (*fs.File, error) { 87 return fs.NewFile(ctx, dirent, flags, &symlinkFileOperations{}), nil 88 } 89 90 // +stateify savable 91 type symlinkFileOperations struct { 92 fsutil.FileNoIoctl `state:"nosave"` 93 fsutil.FileNoMMap `state:"nosave"` 94 fsutil.FileNoRead `state:"nosave"` 95 fsutil.FileNoSeek `state:"nosave"` 96 fsutil.FileNoSplice `state:"nosave"` 97 fsutil.FileNoWrite `state:"nosave"` 98 fsutil.FileNoopFlush `state:"nosave"` 99 fsutil.FileNoopFsync `state:"nosave"` 100 fsutil.FileNoopRelease `state:"nosave"` 101 fsutil.FileNotDirReaddir `state:"nosave"` 102 fsutil.FileUseInodeUnstableAttr `state:"nosave"` 103 waiter.AlwaysReady `state:"nosave"` 104 } 105 106 var _ fs.FileOperations = (*symlinkFileOperations)(nil)