github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsimpl/signalfd/signalfd.go (about) 1 // Copyright 2019 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 signalfd provides basic signalfd file implementations. 16 package signalfd 17 18 import ( 19 "github.com/SagerNet/gvisor/pkg/abi/linux" 20 "github.com/SagerNet/gvisor/pkg/context" 21 "github.com/SagerNet/gvisor/pkg/sentry/kernel" 22 "github.com/SagerNet/gvisor/pkg/sentry/vfs" 23 "github.com/SagerNet/gvisor/pkg/sync" 24 "github.com/SagerNet/gvisor/pkg/syserror" 25 "github.com/SagerNet/gvisor/pkg/usermem" 26 "github.com/SagerNet/gvisor/pkg/waiter" 27 ) 28 29 // SignalFileDescription implements vfs.FileDescriptionImpl for signal fds. 30 // 31 // +stateify savable 32 type SignalFileDescription struct { 33 vfsfd vfs.FileDescription 34 vfs.FileDescriptionDefaultImpl 35 vfs.DentryMetadataFileDescriptionImpl 36 vfs.NoLockFD 37 38 // target is the original signal target task. 39 // 40 // The semantics here are a bit broken. Linux will always use current 41 // for all reads, regardless of where the signalfd originated. We can't 42 // do exactly that because we need to plumb the context through 43 // EventRegister in order to support proper blocking behavior. This 44 // will undoubtedly become very complicated quickly. 45 target *kernel.Task 46 47 // mu protects mask. 48 mu sync.Mutex `state:"nosave"` 49 50 // mask is the signal mask. Protected by mu. 51 mask linux.SignalSet 52 } 53 54 var _ vfs.FileDescriptionImpl = (*SignalFileDescription)(nil) 55 56 // New creates a new signal fd. 57 func New(vfsObj *vfs.VirtualFilesystem, target *kernel.Task, mask linux.SignalSet, flags uint32) (*vfs.FileDescription, error) { 58 vd := vfsObj.NewAnonVirtualDentry("[signalfd]") 59 defer vd.DecRef(target) 60 sfd := &SignalFileDescription{ 61 target: target, 62 mask: mask, 63 } 64 if err := sfd.vfsfd.Init(sfd, flags, vd.Mount(), vd.Dentry(), &vfs.FileDescriptionOptions{ 65 UseDentryMetadata: true, 66 DenyPRead: true, 67 DenyPWrite: true, 68 }); err != nil { 69 return nil, err 70 } 71 return &sfd.vfsfd, nil 72 } 73 74 // Mask returns the signal mask. 75 func (sfd *SignalFileDescription) Mask() linux.SignalSet { 76 sfd.mu.Lock() 77 defer sfd.mu.Unlock() 78 return sfd.mask 79 } 80 81 // SetMask sets the signal mask. 82 func (sfd *SignalFileDescription) SetMask(mask linux.SignalSet) { 83 sfd.mu.Lock() 84 defer sfd.mu.Unlock() 85 sfd.mask = mask 86 } 87 88 // Read implements vfs.FileDescriptionImpl.Read. 89 func (sfd *SignalFileDescription) Read(ctx context.Context, dst usermem.IOSequence, _ vfs.ReadOptions) (int64, error) { 90 // Attempt to dequeue relevant signals. 91 info, err := sfd.target.Sigtimedwait(sfd.Mask(), 0) 92 if err != nil { 93 // There must be no signal available. 94 return 0, syserror.ErrWouldBlock 95 } 96 97 // Copy out the signal info using the specified format. 98 infoNative := linux.SignalfdSiginfo{ 99 Signo: uint32(info.Signo), 100 Errno: info.Errno, 101 Code: info.Code, 102 PID: uint32(info.PID()), 103 UID: uint32(info.UID()), 104 Status: info.Status(), 105 Overrun: uint32(info.Overrun()), 106 Addr: info.Addr(), 107 } 108 n, err := infoNative.WriteTo(dst.Writer(ctx)) 109 if err == usermem.ErrEndOfIOSequence { 110 // Partial copy-out ok. 111 err = nil 112 } 113 return n, err 114 } 115 116 // Readiness implements waiter.Waitable.Readiness. 117 func (sfd *SignalFileDescription) Readiness(mask waiter.EventMask) waiter.EventMask { 118 sfd.mu.Lock() 119 defer sfd.mu.Unlock() 120 if mask&waiter.ReadableEvents != 0 && sfd.target.PendingSignals()&sfd.mask != 0 { 121 return waiter.ReadableEvents // Pending signals. 122 } 123 return 0 124 } 125 126 // EventRegister implements waiter.Waitable.EventRegister. 127 func (sfd *SignalFileDescription) EventRegister(entry *waiter.Entry, _ waiter.EventMask) { 128 sfd.mu.Lock() 129 defer sfd.mu.Unlock() 130 // Register for the signal set; ignore the passed events. 131 sfd.target.SignalRegister(entry, waiter.EventMask(sfd.mask)) 132 } 133 134 // EventUnregister implements waiter.Waitable.EventUnregister. 135 func (sfd *SignalFileDescription) EventUnregister(entry *waiter.Entry) { 136 // Unregister the original entry. 137 sfd.target.SignalUnregister(entry) 138 } 139 140 // Release implements vfs.FileDescriptionImpl.Release. 141 func (sfd *SignalFileDescription) Release(context.Context) {}