Disable fasync for signalfd descriptors

In Linux, signalfd doesn't support fasync events.

Reported-by: syzbot+eeb463868529314bd733@syzkaller.appspotmail.com
PiperOrigin-RevId: 483861398
This commit is contained in:
Andrei Vagin
2022-10-25 21:46:13 -07:00
committed by gVisor bot
parent 5d42fa08b0
commit c1427a04df
8 changed files with 69 additions and 13 deletions
+11
View File
@@ -34,6 +34,7 @@ type SignalFileDescription struct {
vfs.FileDescriptionDefaultImpl
vfs.DentryMetadataFileDescriptionImpl
vfs.NoLockFD
vfs.NoAsyncEventFD
// target is the original signal target task.
//
@@ -155,3 +156,13 @@ func (sfd *SignalFileDescription) Epollable() bool {
func (sfd *SignalFileDescription) Release(context.Context) {
sfd.target.SignalUnregister(&sfd.entry)
}
// RegisterFileAsyncHandler implements vfs.FileDescriptionImpl.RegisterFileAsyncHandler.
func (sfd *SignalFileDescription) RegisterFileAsyncHandler(fd *vfs.FileDescription) error {
return sfd.NoAsyncEventFD.RegisterFileAsyncHandler(fd)
}
// UnregisterFileAsyncHandler implements vfs.FileDescriptionImpl.UnregisterFileAsyncHandler.
func (sfd *SignalFileDescription) UnregisterFileAsyncHandler(fd *vfs.FileDescription) {
sfd.NoAsyncEventFD.UnregisterFileAsyncHandler(fd)
}
+6 -3
View File
@@ -196,7 +196,7 @@ func (fd *FileDescription) DecRef(ctx context.Context) {
fd.vd.DecRef(ctx)
fd.flagsMu.Lock()
if fd.statusFlags.RacyLoad()&linux.O_ASYNC != 0 && fd.asyncHandler != nil {
fd.asyncHandler.Unregister(fd)
fd.impl.UnregisterFileAsyncHandler(fd)
}
fd.asyncHandler = nil
fd.flagsMu.Unlock()
@@ -280,11 +280,11 @@ func (fd *FileDescription) SetStatusFlags(ctx context.Context, creds *auth.Crede
// Use fd.statusFlags instead of oldFlags, which may have become outdated,
// to avoid double registering/unregistering.
if fd.statusFlags.RacyLoad()&linux.O_ASYNC == 0 && flags&linux.O_ASYNC != 0 {
if err := fd.asyncHandler.Register(fd); err != nil {
if err := fd.impl.RegisterFileAsyncHandler(fd); err != nil {
return err
}
} else if fd.statusFlags.RacyLoad()&linux.O_ASYNC != 0 && flags&linux.O_ASYNC == 0 {
fd.asyncHandler.Unregister(fd)
fd.impl.UnregisterFileAsyncHandler(fd)
}
}
fd.statusFlags.Store((oldFlags &^ settableFlags) | (flags & settableFlags))
@@ -474,6 +474,9 @@ type FileDescriptionImpl interface {
// TestPOSIX returns information about whether the specified lock can be held, in the style of the F_GETLK fcntl.
TestPOSIX(ctx context.Context, uid lock.UniqueID, t lock.LockType, r lock.LockRange) (linux.Flock, error)
RegisterFileAsyncHandler(fd *FileDescription) error
UnregisterFileAsyncHandler(fd *FileDescription)
}
// Dirent holds the information contained in struct linux_dirent64.
@@ -172,6 +172,16 @@ func (FileDescriptionDefaultImpl) RemoveXattr(ctx context.Context, name string)
return linuxerr.ENOTSUP
}
// RegisterFileAsyncHandler implements FileDescriptionImpl.RegisterFileAsyncHandler.
func (FileDescriptionDefaultImpl) RegisterFileAsyncHandler(fd *FileDescription) error {
return fd.asyncHandler.Register(fd)
}
// UnregisterFileAsyncHandler implements FileDescriptionImpl.UnregisterFileAsyncHandler.
func (FileDescriptionDefaultImpl) UnregisterFileAsyncHandler(fd *FileDescription) {
fd.asyncHandler.Unregister(fd)
}
// DirectoryFileDescriptionDefaultImpl may be embedded by implementations of
// FileDescriptionImpl that always represent directories to obtain
// implementations of non-directory I/O methods that return EISDIR.
@@ -466,6 +476,18 @@ func (fd *LockFD) TestPOSIX(ctx context.Context, uid fslock.UniqueID, t fslock.L
return fd.locks.TestPOSIX(ctx, uid, t, r)
}
// NoAsyncEventFD implements [Un]RegisterFileAsyncHandler of FileDescriptionImpl.
type NoAsyncEventFD struct{}
// RegisterFileAsyncHandler implements FileDescriptionImpl.RegisterFileAsyncHandler.
func (NoAsyncEventFD) RegisterFileAsyncHandler(fd *FileDescription) error {
return nil
}
// UnregisterFileAsyncHandler implements FileDescriptionImpl.UnregisterFileAsyncHandler.
func (NoAsyncEventFD) UnregisterFileAsyncHandler(fd *FileDescription) {
}
// NoLockFD implements Lock*/Unlock* portion of FileDescriptionImpl interface
// returning ENOLCK.
//
+14
View File
@@ -16,6 +16,7 @@
#include <signal.h>
#include <sys/epoll.h>
#include <sys/mman.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include <syscall.h>
#include <unistd.h>
@@ -1496,6 +1497,19 @@ TEST_F(FcntlSignalTest, SetSigDefault) {
// siginfo contents is undefined in this case.
}
TEST_F(FcntlSignalTest, SignalFD) {
// Create the signalfd.
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGIO);
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewSignalFD(&mask, 0));
const auto signal_cleanup =
ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGIO));
RegisterFD(fd.get(), 0);
int tid = syscall(SYS_gettid);
syscall(SYS_tkill, tid, SIGIO);
}
TEST_F(FcntlSignalTest, SetSigCustom) {
const auto signal_cleanup =
ASSERT_NO_ERRNO_AND_VALUE(RegisterSignalHandler(SIGUSR1));
-10
View File
@@ -42,16 +42,6 @@ constexpr int kSigno = SIGUSR1;
constexpr int kSignoMax = 64; // SIGRTMAX
constexpr int kSignoAlt = SIGUSR2;
// Returns a new signalfd.
inline PosixErrorOr<FileDescriptor> NewSignalFD(sigset_t* mask, int flags = 0) {
int fd = signalfd(-1, mask, flags);
MaybeSave();
if (fd < 0) {
return PosixError(errno, "signalfd");
}
return FileDescriptor(fd);
}
class SignalfdTest : public ::testing::TestWithParam<int> {};
TEST_P(SignalfdTest, Basic) {
+1
View File
@@ -263,6 +263,7 @@ cc_library(
hdrs = ["signal_util.h"],
deps = [
":cleanup",
":file_descriptor",
":posix_error",
":test_util",
gtest,
+11
View File
@@ -15,6 +15,7 @@
#include "test/util/signal_util.h"
#include <signal.h>
#include <sys/signalfd.h>
#include <ostream>
@@ -100,5 +101,15 @@ PosixErrorOr<Cleanup> ScopedSignalMask(int how, sigset_t const& set) {
});
}
// Returns a new signalfd.
PosixErrorOr<FileDescriptor> NewSignalFD(sigset_t* mask, int flags) {
int fd = signalfd(-1, mask, flags);
MaybeSave();
if (fd < 0) {
return PosixError(errno, "signalfd");
}
return FileDescriptor(fd);
}
} // namespace testing
} // namespace gvisor
+4
View File
@@ -23,6 +23,7 @@
#include "gmock/gmock.h"
#include "test/util/cleanup.h"
#include "test/util/file_descriptor.h"
#include "test/util/posix_error.h"
// Format a sigset_t as a comma separated list of numeric ranges.
@@ -101,6 +102,9 @@ inline void FixupFault(ucontext_t* ctx) {
}
#endif
// Wrapper around signalfd(2) that returns a FileDescriptor.
PosixErrorOr<FileDescriptor> NewSignalFD(sigset_t* mask, int flags = 0);
} // namespace testing
} // namespace gvisor