diff --git a/pkg/sentry/kernel/fd_table.go b/pkg/sentry/kernel/fd_table.go index 3eb0ddf69..7277bead7 100644 --- a/pkg/sentry/kernel/fd_table.go +++ b/pkg/sentry/kernel/fd_table.go @@ -267,6 +267,9 @@ func (f *FDTable) NewFDs(ctx context.Context, minFD int32, files []*vfs.FileDesc break } f.fdBitmap.Add(fd) + if fd == uint32(max) { + max = int32(fd + 1) + } if df := f.set(int32(fd), files[len(fds)], flags); df != nil { panic("file set") } diff --git a/test/syscalls/linux/pipe.cc b/test/syscalls/linux/pipe.cc index a4be75908..3fc252208 100644 --- a/test/syscalls/linux/pipe.cc +++ b/test/syscalls/linux/pipe.cc @@ -691,6 +691,31 @@ TEST_P(PipeTest, ZeroSize) { ASSERT_THAT(read(rfd_.get(), nullptr, 0), SyscallSucceedsWithValue(0)); } +// Test that we can open more FDs than the max default value without crashing. +TEST_P(PipeTest, PipeFdCount) { + SKIP_IF(!CreateBlocking()); + + // We make too many calls to go through full save cycles. + DisableSave ds; + constexpr size_t kMaxFd = 66000; + std::vector fds; + + while (true) { + int pipefd[2]; + ASSERT_THAT(pipe2(pipefd, 0), SyscallSucceeds()); + ASSERT_NE(pipefd[0], pipefd[1]); + fds.push_back(pipefd[0]); + fds.push_back(pipefd[1]); + if (static_cast(pipefd[1]) > kMaxFd) { + break; + } + } + + for (const auto fd : fds) { + close(fd); + } +} + std::string PipeCreatorName(::testing::TestParamInfo info) { return info.param.name_; // Use the name specified. }