github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/syscalls/linux/path.go (about) 1 // Copyright 2020 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 linux 16 17 import ( 18 "github.com/MerlinKodo/gvisor/pkg/abi/linux" 19 "github.com/MerlinKodo/gvisor/pkg/errors/linuxerr" 20 "github.com/MerlinKodo/gvisor/pkg/fspath" 21 "github.com/MerlinKodo/gvisor/pkg/hostarch" 22 "github.com/MerlinKodo/gvisor/pkg/sentry/kernel" 23 "github.com/MerlinKodo/gvisor/pkg/sentry/vfs" 24 ) 25 26 func copyInPath(t *kernel.Task, addr hostarch.Addr) (fspath.Path, error) { 27 pathname, err := t.CopyInString(addr, linux.PATH_MAX) 28 if err != nil { 29 return fspath.Path{}, err 30 } 31 return fspath.Parse(pathname), nil 32 } 33 34 type taskPathOperation struct { 35 pop vfs.PathOperation 36 haveStartRef bool 37 } 38 39 func getTaskPathOperation(t *kernel.Task, dirfd int32, path fspath.Path, shouldAllowEmptyPath shouldAllowEmptyPath, shouldFollowFinalSymlink shouldFollowFinalSymlink) (taskPathOperation, error) { 40 root := t.FSContext().RootDirectory() 41 start := root 42 haveStartRef := false 43 if !path.Absolute { 44 if !path.HasComponents() && !bool(shouldAllowEmptyPath) { 45 root.DecRef(t) 46 return taskPathOperation{}, linuxerr.ENOENT 47 } 48 if dirfd == linux.AT_FDCWD { 49 start = t.FSContext().WorkingDirectory() 50 haveStartRef = true 51 } else { 52 dirfile := t.GetFile(dirfd) 53 if dirfile == nil { 54 root.DecRef(t) 55 return taskPathOperation{}, linuxerr.EBADF 56 } 57 start = dirfile.VirtualDentry() 58 start.IncRef() 59 haveStartRef = true 60 dirfile.DecRef(t) 61 } 62 } 63 return taskPathOperation{ 64 pop: vfs.PathOperation{ 65 Root: root, 66 Start: start, 67 Path: path, 68 FollowFinalSymlink: bool(shouldFollowFinalSymlink), 69 }, 70 haveStartRef: haveStartRef, 71 }, nil 72 } 73 74 func (tpop *taskPathOperation) Release(t *kernel.Task) { 75 tpop.pop.Root.DecRef(t) 76 if tpop.haveStartRef { 77 tpop.pop.Start.DecRef(t) 78 tpop.haveStartRef = false 79 } 80 } 81 82 type shouldAllowEmptyPath bool 83 84 const ( 85 disallowEmptyPath shouldAllowEmptyPath = false 86 allowEmptyPath shouldAllowEmptyPath = true 87 ) 88 89 type shouldFollowFinalSymlink bool 90 91 const ( 92 nofollowFinalSymlink shouldFollowFinalSymlink = false 93 followFinalSymlink shouldFollowFinalSymlink = true 94 )