github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/vfs2/filesystem.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/hostarch" 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 // Link implements Linux syscall link(2). 28 func Link(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 29 oldpathAddr := args[0].Pointer() 30 newpathAddr := args[1].Pointer() 31 return 0, nil, linkat(t, linux.AT_FDCWD, oldpathAddr, linux.AT_FDCWD, newpathAddr, 0 /* flags */) 32 } 33 34 // Linkat implements Linux syscall linkat(2). 35 func Linkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 36 olddirfd := args[0].Int() 37 oldpathAddr := args[1].Pointer() 38 newdirfd := args[2].Int() 39 newpathAddr := args[3].Pointer() 40 flags := args[4].Int() 41 return 0, nil, linkat(t, olddirfd, oldpathAddr, newdirfd, newpathAddr, flags) 42 } 43 44 func linkat(t *kernel.Task, olddirfd int32, oldpathAddr hostarch.Addr, newdirfd int32, newpathAddr hostarch.Addr, flags int32) error { 45 if flags&^(linux.AT_EMPTY_PATH|linux.AT_SYMLINK_FOLLOW) != 0 { 46 return linuxerr.EINVAL 47 } 48 if flags&linux.AT_EMPTY_PATH != 0 && !t.HasCapability(linux.CAP_DAC_READ_SEARCH) { 49 return syserror.ENOENT 50 } 51 52 oldpath, err := copyInPath(t, oldpathAddr) 53 if err != nil { 54 return err 55 } 56 oldtpop, err := getTaskPathOperation(t, olddirfd, oldpath, shouldAllowEmptyPath(flags&linux.AT_EMPTY_PATH != 0), shouldFollowFinalSymlink(flags&linux.AT_SYMLINK_FOLLOW != 0)) 57 if err != nil { 58 return err 59 } 60 defer oldtpop.Release(t) 61 62 newpath, err := copyInPath(t, newpathAddr) 63 if err != nil { 64 return err 65 } 66 newtpop, err := getTaskPathOperation(t, newdirfd, newpath, disallowEmptyPath, nofollowFinalSymlink) 67 if err != nil { 68 return err 69 } 70 defer newtpop.Release(t) 71 72 return t.Kernel().VFS().LinkAt(t, t.Credentials(), &oldtpop.pop, &newtpop.pop) 73 } 74 75 // Mkdir implements Linux syscall mkdir(2). 76 func Mkdir(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 77 addr := args[0].Pointer() 78 mode := args[1].ModeT() 79 return 0, nil, mkdirat(t, linux.AT_FDCWD, addr, mode) 80 } 81 82 // Mkdirat implements Linux syscall mkdirat(2). 83 func Mkdirat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 84 dirfd := args[0].Int() 85 addr := args[1].Pointer() 86 mode := args[2].ModeT() 87 return 0, nil, mkdirat(t, dirfd, addr, mode) 88 } 89 90 func mkdirat(t *kernel.Task, dirfd int32, addr hostarch.Addr, mode uint) error { 91 path, err := copyInPath(t, addr) 92 if err != nil { 93 return err 94 } 95 tpop, err := getTaskPathOperation(t, dirfd, path, disallowEmptyPath, nofollowFinalSymlink) 96 if err != nil { 97 return err 98 } 99 defer tpop.Release(t) 100 return t.Kernel().VFS().MkdirAt(t, t.Credentials(), &tpop.pop, &vfs.MkdirOptions{ 101 Mode: linux.FileMode(mode & (0777 | linux.S_ISVTX) &^ t.FSContext().Umask()), 102 }) 103 } 104 105 // Mknod implements Linux syscall mknod(2). 106 func Mknod(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 107 addr := args[0].Pointer() 108 mode := args[1].ModeT() 109 dev := args[2].Uint() 110 return 0, nil, mknodat(t, linux.AT_FDCWD, addr, linux.FileMode(mode), dev) 111 } 112 113 // Mknodat implements Linux syscall mknodat(2). 114 func Mknodat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 115 dirfd := args[0].Int() 116 addr := args[1].Pointer() 117 mode := args[2].ModeT() 118 dev := args[3].Uint() 119 return 0, nil, mknodat(t, dirfd, addr, linux.FileMode(mode), dev) 120 } 121 122 func mknodat(t *kernel.Task, dirfd int32, addr hostarch.Addr, mode linux.FileMode, dev uint32) error { 123 path, err := copyInPath(t, addr) 124 if err != nil { 125 return err 126 } 127 tpop, err := getTaskPathOperation(t, dirfd, path, disallowEmptyPath, nofollowFinalSymlink) 128 if err != nil { 129 return err 130 } 131 defer tpop.Release(t) 132 133 // "Zero file type is equivalent to type S_IFREG." - mknod(2) 134 if mode.FileType() == 0 { 135 mode |= linux.ModeRegular 136 } 137 major, minor := linux.DecodeDeviceID(dev) 138 return t.Kernel().VFS().MknodAt(t, t.Credentials(), &tpop.pop, &vfs.MknodOptions{ 139 Mode: mode &^ linux.FileMode(t.FSContext().Umask()), 140 DevMajor: uint32(major), 141 DevMinor: minor, 142 }) 143 } 144 145 // Open implements Linux syscall open(2). 146 func Open(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 147 addr := args[0].Pointer() 148 flags := args[1].Uint() 149 mode := args[2].ModeT() 150 return openat(t, linux.AT_FDCWD, addr, flags, mode) 151 } 152 153 // Openat implements Linux syscall openat(2). 154 func Openat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 155 dirfd := args[0].Int() 156 addr := args[1].Pointer() 157 flags := args[2].Uint() 158 mode := args[3].ModeT() 159 return openat(t, dirfd, addr, flags, mode) 160 } 161 162 // Creat implements Linux syscall creat(2). 163 func Creat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 164 addr := args[0].Pointer() 165 mode := args[1].ModeT() 166 return openat(t, linux.AT_FDCWD, addr, linux.O_WRONLY|linux.O_CREAT|linux.O_TRUNC, mode) 167 } 168 169 func openat(t *kernel.Task, dirfd int32, pathAddr hostarch.Addr, flags uint32, mode uint) (uintptr, *kernel.SyscallControl, error) { 170 path, err := copyInPath(t, pathAddr) 171 if err != nil { 172 return 0, nil, err 173 } 174 tpop, err := getTaskPathOperation(t, dirfd, path, disallowEmptyPath, shouldFollowFinalSymlink(flags&linux.O_NOFOLLOW == 0)) 175 if err != nil { 176 return 0, nil, err 177 } 178 defer tpop.Release(t) 179 180 file, err := t.Kernel().VFS().OpenAt(t, t.Credentials(), &tpop.pop, &vfs.OpenOptions{ 181 Flags: flags | linux.O_LARGEFILE, 182 Mode: linux.FileMode(mode & (0777 | linux.S_ISUID | linux.S_ISGID | linux.S_ISVTX) &^ t.FSContext().Umask()), 183 }) 184 if err != nil { 185 return 0, nil, err 186 } 187 defer file.DecRef(t) 188 189 fd, err := t.NewFDFromVFS2(0, file, kernel.FDFlags{ 190 CloseOnExec: flags&linux.O_CLOEXEC != 0, 191 }) 192 return uintptr(fd), nil, err 193 } 194 195 // Rename implements Linux syscall rename(2). 196 func Rename(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 197 oldpathAddr := args[0].Pointer() 198 newpathAddr := args[1].Pointer() 199 return 0, nil, renameat(t, linux.AT_FDCWD, oldpathAddr, linux.AT_FDCWD, newpathAddr, 0 /* flags */) 200 } 201 202 // Renameat implements Linux syscall renameat(2). 203 func Renameat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 204 olddirfd := args[0].Int() 205 oldpathAddr := args[1].Pointer() 206 newdirfd := args[2].Int() 207 newpathAddr := args[3].Pointer() 208 return 0, nil, renameat(t, olddirfd, oldpathAddr, newdirfd, newpathAddr, 0 /* flags */) 209 } 210 211 // Renameat2 implements Linux syscall renameat2(2). 212 func Renameat2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 213 olddirfd := args[0].Int() 214 oldpathAddr := args[1].Pointer() 215 newdirfd := args[2].Int() 216 newpathAddr := args[3].Pointer() 217 flags := args[4].Uint() 218 return 0, nil, renameat(t, olddirfd, oldpathAddr, newdirfd, newpathAddr, flags) 219 } 220 221 func renameat(t *kernel.Task, olddirfd int32, oldpathAddr hostarch.Addr, newdirfd int32, newpathAddr hostarch.Addr, flags uint32) error { 222 oldpath, err := copyInPath(t, oldpathAddr) 223 if err != nil { 224 return err 225 } 226 // "If oldpath refers to a symbolic link, the link is renamed" - rename(2) 227 oldtpop, err := getTaskPathOperation(t, olddirfd, oldpath, disallowEmptyPath, nofollowFinalSymlink) 228 if err != nil { 229 return err 230 } 231 defer oldtpop.Release(t) 232 233 newpath, err := copyInPath(t, newpathAddr) 234 if err != nil { 235 return err 236 } 237 newtpop, err := getTaskPathOperation(t, newdirfd, newpath, disallowEmptyPath, nofollowFinalSymlink) 238 if err != nil { 239 return err 240 } 241 defer newtpop.Release(t) 242 243 return t.Kernel().VFS().RenameAt(t, t.Credentials(), &oldtpop.pop, &newtpop.pop, &vfs.RenameOptions{ 244 Flags: flags, 245 }) 246 } 247 248 // Rmdir implements Linux syscall rmdir(2). 249 func Rmdir(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 250 pathAddr := args[0].Pointer() 251 return 0, nil, rmdirat(t, linux.AT_FDCWD, pathAddr) 252 } 253 254 func rmdirat(t *kernel.Task, dirfd int32, pathAddr hostarch.Addr) error { 255 path, err := copyInPath(t, pathAddr) 256 if err != nil { 257 return err 258 } 259 tpop, err := getTaskPathOperation(t, dirfd, path, disallowEmptyPath, nofollowFinalSymlink) 260 if err != nil { 261 return err 262 } 263 defer tpop.Release(t) 264 return t.Kernel().VFS().RmdirAt(t, t.Credentials(), &tpop.pop) 265 } 266 267 // Unlink implements Linux syscall unlink(2). 268 func Unlink(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 269 pathAddr := args[0].Pointer() 270 return 0, nil, unlinkat(t, linux.AT_FDCWD, pathAddr) 271 } 272 273 func unlinkat(t *kernel.Task, dirfd int32, pathAddr hostarch.Addr) error { 274 path, err := copyInPath(t, pathAddr) 275 if err != nil { 276 return err 277 } 278 tpop, err := getTaskPathOperation(t, dirfd, path, disallowEmptyPath, nofollowFinalSymlink) 279 if err != nil { 280 return err 281 } 282 defer tpop.Release(t) 283 return t.Kernel().VFS().UnlinkAt(t, t.Credentials(), &tpop.pop) 284 } 285 286 // Unlinkat implements Linux syscall unlinkat(2). 287 func Unlinkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 288 dirfd := args[0].Int() 289 pathAddr := args[1].Pointer() 290 flags := args[2].Int() 291 292 if flags&^linux.AT_REMOVEDIR != 0 { 293 return 0, nil, linuxerr.EINVAL 294 } 295 296 if flags&linux.AT_REMOVEDIR != 0 { 297 return 0, nil, rmdirat(t, dirfd, pathAddr) 298 } 299 return 0, nil, unlinkat(t, dirfd, pathAddr) 300 } 301 302 // Symlink implements Linux syscall symlink(2). 303 func Symlink(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 304 targetAddr := args[0].Pointer() 305 linkpathAddr := args[1].Pointer() 306 return 0, nil, symlinkat(t, targetAddr, linux.AT_FDCWD, linkpathAddr) 307 } 308 309 // Symlinkat implements Linux syscall symlinkat(2). 310 func Symlinkat(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 311 targetAddr := args[0].Pointer() 312 newdirfd := args[1].Int() 313 linkpathAddr := args[2].Pointer() 314 return 0, nil, symlinkat(t, targetAddr, newdirfd, linkpathAddr) 315 } 316 317 func symlinkat(t *kernel.Task, targetAddr hostarch.Addr, newdirfd int32, linkpathAddr hostarch.Addr) error { 318 target, err := t.CopyInString(targetAddr, linux.PATH_MAX) 319 if err != nil { 320 return err 321 } 322 if len(target) == 0 { 323 return syserror.ENOENT 324 } 325 linkpath, err := copyInPath(t, linkpathAddr) 326 if err != nil { 327 return err 328 } 329 tpop, err := getTaskPathOperation(t, newdirfd, linkpath, disallowEmptyPath, nofollowFinalSymlink) 330 if err != nil { 331 return err 332 } 333 defer tpop.Release(t) 334 return t.Kernel().VFS().SymlinkAt(t, t.Credentials(), &tpop.pop, target) 335 }