github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/vfs2/fscontext.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 vfs2 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/abi/linux" 19 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 20 "github.com/SagerNet/gvisor/pkg/fspath" 21 "github.com/SagerNet/gvisor/pkg/sentry/arch" 22 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 23 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 24 "github.com/SagerNet/gvisor/pkg/syserror" 25 ) 26 27 // Getcwd implements Linux syscall getcwd(2). 28 func Getcwd(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 29 addr := args[0].Pointer() 30 size := args[1].SizeT() 31 32 root := t.FSContext().RootDirectoryVFS2() 33 wd := t.FSContext().WorkingDirectoryVFS2() 34 s, err := t.Kernel().VFS().PathnameForGetcwd(t, root, wd) 35 root.DecRef(t) 36 wd.DecRef(t) 37 if err != nil { 38 return 0, nil, err 39 } 40 41 // Note this is >= because we need a terminator. 42 if uint(len(s)) >= size { 43 return 0, nil, syserror.ERANGE 44 } 45 46 // Construct a byte slice containing a NUL terminator. 47 buf := t.CopyScratchBuffer(len(s) + 1) 48 copy(buf, s) 49 buf[len(buf)-1] = 0 50 51 // Write the pathname slice. 52 n, err := t.CopyOutBytes(addr, buf) 53 if err != nil { 54 return 0, nil, err 55 } 56 return uintptr(n), nil, nil 57 } 58 59 // Chdir implements Linux syscall chdir(2). 60 func Chdir(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 61 addr := args[0].Pointer() 62 63 path, err := copyInPath(t, addr) 64 if err != nil { 65 return 0, nil, err 66 } 67 tpop, err := getTaskPathOperation(t, linux.AT_FDCWD, path, disallowEmptyPath, followFinalSymlink) 68 if err != nil { 69 return 0, nil, err 70 } 71 defer tpop.Release(t) 72 73 vd, err := t.Kernel().VFS().GetDentryAt(t, t.Credentials(), &tpop.pop, &vfs.GetDentryOptions{ 74 CheckSearchable: true, 75 }) 76 if err != nil { 77 return 0, nil, err 78 } 79 t.FSContext().SetWorkingDirectoryVFS2(t, vd) 80 vd.DecRef(t) 81 return 0, nil, nil 82 } 83 84 // Fchdir implements Linux syscall fchdir(2). 85 func Fchdir(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 86 fd := args[0].Int() 87 88 tpop, err := getTaskPathOperation(t, fd, fspath.Path{}, allowEmptyPath, nofollowFinalSymlink) 89 if err != nil { 90 return 0, nil, err 91 } 92 defer tpop.Release(t) 93 94 vd, err := t.Kernel().VFS().GetDentryAt(t, t.Credentials(), &tpop.pop, &vfs.GetDentryOptions{ 95 CheckSearchable: true, 96 }) 97 if err != nil { 98 return 0, nil, err 99 } 100 t.FSContext().SetWorkingDirectoryVFS2(t, vd) 101 vd.DecRef(t) 102 return 0, nil, nil 103 } 104 105 // Chroot implements Linux syscall chroot(2). 106 func Chroot(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 107 addr := args[0].Pointer() 108 109 if !t.HasCapability(linux.CAP_SYS_CHROOT) { 110 return 0, nil, linuxerr.EPERM 111 } 112 113 path, err := copyInPath(t, addr) 114 if err != nil { 115 return 0, nil, err 116 } 117 tpop, err := getTaskPathOperation(t, linux.AT_FDCWD, path, disallowEmptyPath, followFinalSymlink) 118 if err != nil { 119 return 0, nil, err 120 } 121 defer tpop.Release(t) 122 123 vd, err := t.Kernel().VFS().GetDentryAt(t, t.Credentials(), &tpop.pop, &vfs.GetDentryOptions{ 124 CheckSearchable: true, 125 }) 126 if err != nil { 127 return 0, nil, err 128 } 129 t.FSContext().SetRootDirectoryVFS2(t, vd) 130 vd.DecRef(t) 131 return 0, nil, nil 132 }