Don't eat error from epoll_ctl EPOLL_CTL_ADD

Docker maps stdin to `/dev/null` which doesn't support epoll. Host FD
was ignoring the error and suceeding the epoll_ctl call from the
container, giving false impressing that epoll would be notified.

This required plumbing failure to all waiter.Waitable.EventRegister
callers and implementers.

Closes #6795

PiperOrigin-RevId: 414797621
This commit is contained in:
Fabricio Voznika
2021-12-07 12:36:00 -08:00
committed by gVisor bot
parent d62190f8b5
commit 9768009a79
54 changed files with 359 additions and 141 deletions
+28 -1
View File
@@ -13,11 +13,13 @@
// limitations under the License.
#include <err.h>
#include <errno.h>
#include <sys/epoll.h>
#include <sys/ioctl.h>
#include <unistd.h>
// Tests that FIONREAD is supported with host FD.
int main(int argc, char** argv) {
void testFionread() {
int size = 0;
if (ioctl(STDOUT_FILENO, FIONREAD, &size) < 0) {
err(1, "ioctl(stdin, FIONREAD)");
@@ -25,5 +27,30 @@ int main(int argc, char** argv) {
if (size != 0) {
err(1, "FIONREAD wrong size, want: 0, got: %d", size);
}
}
// Docker maps stdin to /dev/null which doesn't support epoll. Check that error
// is correctly propagated.
void testEpoll() {
int fd = epoll_create(1);
if (fd < 0) {
err(1, "epoll_create");
}
struct epoll_event event;
event.events = EPOLLIN;
event.data.u64 = 123;
int res = epoll_ctl(fd, EPOLL_CTL_ADD, 0, &event);
if (res != -1) {
err(1, "epoll_ctl(EPOLL_CTL_ADD, stdin) should have failed");
}
if (errno != EPERM) {
err(1, "epoll_ctl(EPOLL_CTL_ADD, stdin) should have returned EPERM");
}
}
int main(int argc, char** argv) {
testFionread();
testEpoll();
return 0;
}
+2 -1
View File
@@ -152,8 +152,9 @@ func (fd *tunFD) Readiness(mask waiter.EventMask) waiter.EventMask {
}
// EventRegister implements watier.Waitable.EventRegister.
func (fd *tunFD) EventRegister(e *waiter.Entry) {
func (fd *tunFD) EventRegister(e *waiter.Entry) error {
fd.device.EventRegister(e)
return nil
}
// EventUnregister implements watier.Waitable.EventUnregister.
+2 -1
View File
@@ -158,8 +158,9 @@ func (n *netTunFileOperations) Readiness(mask waiter.EventMask) waiter.EventMask
}
// EventRegister implements watier.Waitable.EventRegister.
func (n *netTunFileOperations) EventRegister(e *waiter.Entry) {
func (n *netTunFileOperations) EventRegister(e *waiter.Entry) error {
n.device.EventRegister(e)
return nil
}
// EventUnregister implements watier.Waitable.EventUnregister.
+10 -3
View File
@@ -16,6 +16,7 @@
package fdpipe
import (
"fmt"
"os"
"golang.org/x/sys/unix"
@@ -99,15 +100,21 @@ func (p *pipeOperations) init() error {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (p *pipeOperations) EventRegister(e *waiter.Entry) {
func (p *pipeOperations) EventRegister(e *waiter.Entry) error {
p.Queue.EventRegister(e)
fdnotifier.UpdateFD(int32(p.file.FD()))
if err := fdnotifier.UpdateFD(int32(p.file.FD())); err != nil {
p.Queue.EventUnregister(e)
return err
}
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
func (p *pipeOperations) EventUnregister(e *waiter.Entry) {
p.Queue.EventUnregister(e)
fdnotifier.UpdateFD(int32(p.file.FD()))
if err := fdnotifier.UpdateFD(int32(p.file.FD())); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
}
// Readiness returns a mask of ready events for stream.
+10 -7
View File
@@ -159,7 +159,8 @@ func (f *File) SetFlags(newFlags SettableFileFlags) {
f.flags.Append = newFlags.Append
if f.async != nil {
if newFlags.Async && !f.flags.Async {
f.async.Register(f)
// Ignore error given that VFS1 will not be here much longer.
_ = f.async.Register(f)
}
if !newFlags.Async && f.flags.Async {
f.async.Unregister(f)
@@ -180,8 +181,8 @@ func (f *File) Readiness(mask waiter.EventMask) waiter.EventMask {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (f *File) EventRegister(e *waiter.Entry) {
f.FileOperations.EventRegister(e)
func (f *File) EventRegister(e *waiter.Entry) error {
return f.FileOperations.EventRegister(e)
}
// EventUnregister implements waiter.Waitable.EventUnregister.
@@ -424,23 +425,25 @@ func (f *File) Msync(ctx context.Context, mr memmap.MappableRange) error {
// A FileAsync sends signals to its owner when w is ready for IO.
type FileAsync interface {
Register(w waiter.Waitable)
Register(w waiter.Waitable) error
Unregister(w waiter.Waitable)
}
// Async gets the stored FileAsync or creates a new one with the supplied
// function. If the supplied function is nil, no FileAsync is created and the
// current value is returned.
func (f *File) Async(newAsync func() FileAsync) FileAsync {
func (f *File) Async(newAsync func() FileAsync) (FileAsync, error) {
f.flagsMu.Lock()
defer f.flagsMu.Unlock()
if f.async == nil && newAsync != nil {
f.async = newAsync()
if f.flags.Async {
f.async.Register(f)
if err := f.async.Register(f); err != nil {
return nil, err
}
}
}
return f.async
return f.async, nil
}
// lockedReader implements io.Reader and io.ReaderAt.
+3 -4
View File
@@ -100,14 +100,13 @@ func (f *overlayFileOperations) Release(ctx context.Context) {
}
// EventRegister implements FileOperations.EventRegister.
func (f *overlayFileOperations) EventRegister(we *waiter.Entry) {
func (f *overlayFileOperations) EventRegister(we *waiter.Entry) error {
f.upperMu.Lock()
defer f.upperMu.Unlock()
if f.upper != nil {
f.upper.EventRegister(we)
return
return f.upper.EventRegister(we)
}
f.lower.EventRegister(we)
return f.lower.EventRegister(we)
}
// EventUnregister implements FileOperations.Unregister.
+5 -1
View File
@@ -14,6 +14,8 @@
package fs
import "fmt"
// beforeSave is invoked by stateify.
func (f *File) beforeSave() {
f.saving = true
@@ -25,6 +27,8 @@ func (f *File) beforeSave() {
// afterLoad is invoked by stateify.
func (f *File) afterLoad() {
if f.flags.Async && f.async != nil {
f.async.Register(f)
if err := f.async.Register(f); err != nil {
panic(fmt.Sprint("async.Register:", err))
}
}
}
+9 -3
View File
@@ -149,15 +149,21 @@ func newFile(ctx context.Context, dirent *fs.Dirent, flags fs.FileFlags, iops *i
}
// EventRegister implements waiter.Waitable.EventRegister.
func (f *fileOperations) EventRegister(e *waiter.Entry) {
func (f *fileOperations) EventRegister(e *waiter.Entry) error {
f.iops.fileState.queue.EventRegister(e)
fdnotifier.UpdateFD(int32(f.iops.fileState.FD()))
if err := fdnotifier.UpdateFD(int32(f.iops.fileState.FD())); err != nil {
f.iops.fileState.queue.EventUnregister(e)
return err
}
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
func (f *fileOperations) EventUnregister(e *waiter.Entry) {
f.iops.fileState.queue.EventUnregister(e)
fdnotifier.UpdateFD(int32(f.iops.fileState.FD()))
if err := fdnotifier.UpdateFD(int32(f.iops.fileState.FD())); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
}
// Readiness uses the poll() syscall to check the status of the underlying FD.
+5 -2
View File
@@ -259,12 +259,15 @@ func (c *ConnectedEndpoint) GetLocalAddress() (tcpip.FullAddress, tcpip.Error) {
}
// EventUpdate implements transport.ConnectedEndpoint.EventUpdate.
func (c *ConnectedEndpoint) EventUpdate() {
func (c *ConnectedEndpoint) EventUpdate() error {
c.mu.RLock()
defer c.mu.RUnlock()
if c.file.FD() != -1 {
fdnotifier.UpdateFD(int32(c.file.FD()))
if err := fdnotifier.UpdateFD(int32(c.file.FD())); err != nil {
return err
}
}
return nil
}
// Recv implements transport.Receiver.Recv.
+6
View File
@@ -351,3 +351,9 @@ func (i *Inotify) RmWatch(ctx context.Context, wd int32) error {
return nil
}
// EventRegister implements waiter.Waitable.
func (i *Inotify) EventRegister(e *waiter.Entry) error {
i.Queue.EventRegister(e)
return nil
}
+2 -1
View File
@@ -108,8 +108,9 @@ func (t *TimerOperations) Readiness(mask waiter.EventMask) waiter.EventMask {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (t *TimerOperations) EventRegister(e *waiter.Entry) {
func (t *TimerOperations) EventRegister(e *waiter.Entry) error {
t.events.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+2 -1
View File
@@ -128,8 +128,9 @@ func (mf *masterFileOperations) Release(ctx context.Context) {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (mf *masterFileOperations) EventRegister(e *waiter.Entry) {
func (mf *masterFileOperations) EventRegister(e *waiter.Entry) error {
mf.t.ld.masterWaiter.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+2 -1
View File
@@ -113,8 +113,9 @@ func (sf *replicaFileOperations) Release(context.Context) {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (sf *replicaFileOperations) EventRegister(e *waiter.Entry) {
func (sf *replicaFileOperations) EventRegister(e *waiter.Entry) error {
sf.si.t.ld.replicaWaiter.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+2 -1
View File
@@ -103,8 +103,9 @@ func (mfd *masterFileDescription) Release(ctx context.Context) {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (mfd *masterFileDescription) EventRegister(e *waiter.Entry) {
func (mfd *masterFileDescription) EventRegister(e *waiter.Entry) error {
mfd.t.ld.masterWaiter.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+2 -1
View File
@@ -112,8 +112,9 @@ var _ vfs.FileDescriptionImpl = (*replicaFileDescription)(nil)
func (rfd *replicaFileDescription) Release(ctx context.Context) {}
// EventRegister implements waiter.Waitable.EventRegister.
func (rfd *replicaFileDescription) EventRegister(e *waiter.Entry) {
func (rfd *replicaFileDescription) EventRegister(e *waiter.Entry) error {
rfd.inode.t.ld.replicaWaiter.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+10 -3
View File
@@ -16,6 +16,7 @@
package eventfd
import (
"fmt"
"math"
"sync"
@@ -266,14 +267,18 @@ func (efd *EventFileDescription) Readiness(mask waiter.EventMask) waiter.EventMa
}
// EventRegister implements waiter.Waitable.EventRegister.
func (efd *EventFileDescription) EventRegister(entry *waiter.Entry) {
func (efd *EventFileDescription) EventRegister(entry *waiter.Entry) error {
efd.queue.EventRegister(entry)
efd.mu.Lock()
defer efd.mu.Unlock()
if efd.hostfd >= 0 {
fdnotifier.UpdateFD(int32(efd.hostfd))
if err := fdnotifier.UpdateFD(int32(efd.hostfd)); err != nil {
efd.queue.EventUnregister(entry)
return err
}
}
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
@@ -283,6 +288,8 @@ func (efd *EventFileDescription) EventUnregister(entry *waiter.Entry) {
efd.mu.Lock()
defer efd.mu.Unlock()
if efd.hostfd >= 0 {
fdnotifier.UpdateFD(int32(efd.hostfd))
if err := fdnotifier.UpdateFD(int32(efd.hostfd)); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
}
}
+3 -1
View File
@@ -49,7 +49,9 @@ func TestEventFD(t *testing.T) {
// Register a callback for a write event.
w, ch := waiter.NewChannelEntry(waiter.ReadableEvents)
eventfd.EventRegister(&w)
if err := eventfd.EventRegister(&w); err != nil {
t.Fatalf("EventRegister(): %v", err)
}
defer eventfd.EventUnregister(&w)
data := []byte("00000124")
+2 -1
View File
@@ -378,8 +378,9 @@ func (fd *DeviceFD) readinessLocked(mask waiter.EventMask) waiter.EventMask {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (fd *DeviceFD) EventRegister(e *waiter.Entry) {
func (fd *DeviceFD) EventRegister(e *waiter.Entry) error {
fd.waitQueue.EventRegister(e)
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
+11 -5
View File
@@ -15,6 +15,7 @@
package gofer
import (
"fmt"
"sync/atomic"
"golang.org/x/sys/unix"
@@ -165,20 +166,25 @@ func (fd *specialFileFD) Readiness(mask waiter.EventMask) waiter.EventMask {
}
// EventRegister implements waiter.Waitable.EventRegister.
func (fd *specialFileFD) EventRegister(e *waiter.Entry) {
func (fd *specialFileFD) EventRegister(e *waiter.Entry) error {
if fd.haveQueue {
fd.queue.EventRegister(e)
fdnotifier.UpdateFD(fd.handle.fd)
return
if err := fdnotifier.UpdateFD(fd.handle.fd); err != nil {
fd.queue.EventUnregister(e)
return err
}
return nil
}
fd.fileDescription.EventRegister(e)
return fd.fileDescription.EventRegister(e)
}
// EventUnregister implements waiter.Waitable.EventUnregister.
func (fd *specialFileFD) EventUnregister(e *waiter.Entry) {
if fd.haveQueue {
fd.queue.EventUnregister(e)
fdnotifier.UpdateFD(fd.handle.fd)
if err := fdnotifier.UpdateFD(fd.handle.fd); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
return
}
fd.fileDescription.EventUnregister(e)
+9 -3
View File
@@ -907,18 +907,24 @@ func (f *fileDescription) ConfigureMMap(_ context.Context, opts *memmap.MMapOpts
}
// EventRegister implements waiter.Waitable.EventRegister.
func (f *fileDescription) EventRegister(e *waiter.Entry) {
func (f *fileDescription) EventRegister(e *waiter.Entry) error {
f.inode.queue.EventRegister(e)
if f.inode.mayBlock {
fdnotifier.UpdateFD(int32(f.inode.hostFD))
if err := fdnotifier.UpdateFD(int32(f.inode.hostFD)); err != nil {
f.inode.queue.EventUnregister(e)
return err
}
}
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
func (f *fileDescription) EventUnregister(e *waiter.Entry) {
f.inode.queue.EventUnregister(e)
if f.inode.mayBlock {
fdnotifier.UpdateFD(int32(f.inode.hostFD))
if err := fdnotifier.UpdateFD(int32(f.inode.hostFD)); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
}
}

Some files were not shown because too many files have changed in this diff Show More