From e153f44ce8e096327df6b5fbc648f4c949f93175 Mon Sep 17 00:00:00 2001 From: Benjamin Lamowski Date: Fri, 14 Jun 2024 09:02:32 +0200 Subject: [PATCH] libc: handle invalid file descriptors in poll() poll(2) needs to handle invalid file descriptors in the pollfd struct, specifically -1 as it may be used to disable entries in the fds[] array. Fix a possible nullptr dereference by checking the File_descriptor pointer returned by find_by_libc_fd() for validity and skip processing of any unresolved FDs, effectively implementing standard POSIX semantics. Fixes #5249 --- repos/libports/src/lib/libc/poll.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/repos/libports/src/lib/libc/poll.cc b/repos/libports/src/lib/libc/poll.cc index 1f8a4c85e6..0e526559e7 100644 --- a/repos/libports/src/lib/libc/poll.cc +++ b/repos/libports/src/lib/libc/poll.cc @@ -54,7 +54,8 @@ static int poll_plugins(Plugin::Pollfd pollfds[], int nfds) int plugin_nfds = 0; for (int pollfd_index = 0; pollfd_index < nfds; pollfd_index++) - if (pollfds[pollfd_index].fdo->plugin == plugin) + if (pollfds[pollfd_index].fdo && + pollfds[pollfd_index].fdo->plugin == plugin) plugin_nfds++; if (plugin_nfds == 0) @@ -71,7 +72,8 @@ static int poll_plugins(Plugin::Pollfd pollfds[], int nfds) pollfd_index < nfds; pollfd_index++) { - if (pollfds[pollfd_index].fdo->plugin == plugin) { + if (pollfds[pollfd_index].fdo && + pollfds[pollfd_index].fdo->plugin == plugin) { plugin_pollfds[plugin_pollfd_index] = pollfds[pollfd_index]; plugin_pollfd_index++; } @@ -96,6 +98,12 @@ poll(struct pollfd pollfds[], nfds_t nfds, int timeout_ms) /* * Look up the file descriptor objects early-on to reduce repeated * overhead. + * + * According to POSIX poll(2), a poolfd entry is ignored if 'fd' is + * negative, but 'revents' must be cleared (set to zero) nevertheless. + * Note, negative file descriptors result in a nullptr in fdo on calls to + * 'find_by_libc_fd()', which is checked against above and will result in + * the file descriptor being skipped. */ Plugin::Pollfd plugins_pollfds[nfds];