github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/syscalls/linux/sys_pipe.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 linux 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/marshal/primitive" 22 "github.com/SagerNet/gvisor/pkg/sentry/arch" 23 "github.com/SagerNet/gvisor/pkg/sentry/fs" 24 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 25 "github.com/SagerNet/gvisor/pkg/sentry/kernel/pipe" 26 ) 27 28 // LINT.IfChange 29 30 // pipe2 implements the actual system call with flags. 31 func pipe2(t *kernel.Task, addr hostarch.Addr, flags uint) (uintptr, error) { 32 if flags&^(linux.O_NONBLOCK|linux.O_CLOEXEC) != 0 { 33 return 0, linuxerr.EINVAL 34 } 35 r, w := pipe.NewConnectedPipe(t, pipe.DefaultPipeSize) 36 37 r.SetFlags(linuxToFlags(flags).Settable()) 38 defer r.DecRef(t) 39 40 w.SetFlags(linuxToFlags(flags).Settable()) 41 defer w.DecRef(t) 42 43 fds, err := t.NewFDs(0, []*fs.File{r, w}, kernel.FDFlags{ 44 CloseOnExec: flags&linux.O_CLOEXEC != 0, 45 }) 46 if err != nil { 47 return 0, err 48 } 49 50 if _, err := primitive.CopyInt32SliceOut(t, addr, fds); err != nil { 51 for _, fd := range fds { 52 if file, _ := t.FDTable().Remove(t, fd); file != nil { 53 file.DecRef(t) 54 } 55 } 56 return 0, err 57 } 58 return 0, nil 59 } 60 61 // Pipe implements linux syscall pipe(2). 62 func Pipe(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 63 addr := args[0].Pointer() 64 65 n, err := pipe2(t, addr, 0) 66 return n, nil, err 67 } 68 69 // Pipe2 implements linux syscall pipe2(2). 70 func Pipe2(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { 71 addr := args[0].Pointer() 72 flags := uint(args[1].Uint()) 73 74 n, err := pipe2(t, addr, flags) 75 return n, nil, err 76 } 77 78 // LINT.ThenChange(vfs2/pipe.go)