From b2bedca67ed1c0f62ad14c2c2d29f2a1188585b5 Mon Sep 17 00:00:00 2001 From: Marcin Mielniczuk Date: Fri, 31 Jan 2020 22:05:53 +0100 Subject: [PATCH] Fix a possible overflow due to use of fionread in poll_oneoff on Unix. Closes #578. --- .../src/sys/unix/hostcalls_impl/misc.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs b/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs index 30adda29ed7b..9b6611b0c369 100644 --- a/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs +++ b/crates/wasi-common/src/sys/unix/hostcalls_impl/misc.rs @@ -126,9 +126,21 @@ fn poll_oneoff_handle_fd_event<'a>( ready_events: impl Iterator, yanix::poll::PollFd)>, events: &mut Vec, ) -> Result<()> { + use crate::fdentry::Descriptor; use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use yanix::{file::fionread, poll::PollFlags}; + fn query_nbytes(fd: &Descriptor) -> Result { + // fionread may overflow for large files, so use another way for regular files. + if let Descriptor::OsHandle(os_handle) = fd { + let meta = os_handle.metadata()?; + if meta.file_type().is_file() { + return meta.len().try_into().map_err(Into::into); + } + } + unsafe { fionread(fd.as_raw_fd()) }.map_err(Into::into) + } + for (fd_event, poll_fd) in ready_events { log::debug!("poll_oneoff_handle_fd_event fd_event = {:?}", fd_event); log::debug!("poll_oneoff_handle_fd_event poll_fd = {:?}", poll_fd); @@ -141,7 +153,7 @@ fn poll_oneoff_handle_fd_event<'a>( log::debug!("poll_oneoff_handle_fd_event revents = {:?}", revents); let nbytes = if fd_event.r#type == wasi::__WASI_EVENTTYPE_FD_READ { - unsafe { fionread(fd_event.descriptor.as_raw_fd())? } + query_nbytes(fd_event.descriptor)? } else { 0 };