tree-wide: check POLLNVAL everywhere
poll() sets POLLNVAL inside of the poll structures if an invalid fd is passed. So far we generally didn't check for that, thus not taking notice of the error. Given that this specific kind of error is generally indication of a programming error, and given that our code is embedded into our projects via NSS or because people link against our library, let's explicitly check for this and convert it to EBADF. (I ran into a busy loop because of this missing check when some of my test code accidentally closed an fd it shouldn't close, so this is a real thing)
This commit is contained in:
parent
45204921be
commit
dad28bffd6
|
@ -33,10 +33,13 @@ int flush_fd(int fd) {
|
|||
continue;
|
||||
|
||||
return -errno;
|
||||
|
||||
} else if (r == 0)
|
||||
}
|
||||
if (r == 0)
|
||||
return count;
|
||||
|
||||
if (pollfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
l = read(fd, buf, sizeof(buf));
|
||||
if (l < 0) {
|
||||
|
||||
|
@ -169,6 +172,9 @@ int pipe_eof(int fd) {
|
|||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (pollfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
return pollfd.revents & POLLHUP;
|
||||
}
|
||||
|
||||
|
@ -188,6 +194,9 @@ int fd_wait_for_event(int fd, int event, usec_t t) {
|
|||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (pollfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
return pollfd.revents;
|
||||
}
|
||||
|
||||
|
|
|
@ -1002,6 +1002,9 @@ int flush_accept(int fd) {
|
|||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (pollfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
if (iteration >= MAX_FLUSH_ITERATIONS)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
|
||||
"Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
|
||||
|
|
|
@ -2093,10 +2093,13 @@ static int wait_for_change(sd_journal *j, int poll_fd) {
|
|||
return log_error_errno(errno, "Couldn't wait for journal event: %m");
|
||||
}
|
||||
|
||||
if (pollfds[1].revents & (POLLHUP|POLLERR)) /* STDOUT has been closed? */
|
||||
if (pollfds[1].revents & (POLLHUP|POLLERR|POLLNVAL)) /* STDOUT has been closed? */
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ECANCELED),
|
||||
"Standard output has been closed.");
|
||||
|
||||
if (pollfds[0].revents & POLLNVAL)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EBADF), "Change fd closed?");
|
||||
|
||||
r = sd_journal_process(j);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to process journal events: %m");
|
||||
|
|
|
@ -1275,6 +1275,8 @@ int bus_socket_process_opening(sd_bus *b) {
|
|||
r = poll(&p, 1, 0);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (p.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
|
||||
return 0;
|
||||
|
|
|
@ -3121,8 +3121,15 @@ static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
|
|||
r = ppoll(p, n, m == USEC_INFINITY ? NULL : timespec_store(&ts, m), NULL);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
return r > 0 ? 1 : 0;
|
||||
if (p[0].revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
if (n >= 2 && (p[1].revents & POLLNVAL))
|
||||
return -EBADF;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
|
||||
|
|
|
@ -577,6 +577,8 @@ _public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) {
|
|||
return -errno;
|
||||
if (r == 0)
|
||||
return -ETIMEDOUT;
|
||||
if (pfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -462,7 +462,6 @@ static usec_t calc_elapse(uint64_t usec) {
|
|||
}
|
||||
|
||||
static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
|
||||
struct pollfd p[1] = {};
|
||||
struct timespec ts;
|
||||
usec_t m = USEC_INFINITY;
|
||||
int r, e;
|
||||
|
@ -495,14 +494,21 @@ static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
|
|||
if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
|
||||
m = timeout_usec;
|
||||
|
||||
p[0].fd = rtnl->fd;
|
||||
p[0].events = e;
|
||||
struct pollfd p = {
|
||||
.fd = rtnl->fd,
|
||||
.events = e,
|
||||
};
|
||||
|
||||
r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
|
||||
r = ppoll(&p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
return r > 0 ? 1 : 0;
|
||||
if (p.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
|
||||
|
|
|
@ -216,8 +216,11 @@ static int udev_monitor_receive_sd_device(struct udev_monitor *udev_monitor, sd_
|
|||
continue;
|
||||
|
||||
return -errno;
|
||||
} else if (r == 0)
|
||||
}
|
||||
if (r == 0)
|
||||
return -EAGAIN;
|
||||
if (pfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
/* receive next message */
|
||||
break;
|
||||
|
|
|
@ -305,6 +305,12 @@ int ask_password_plymouth(
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (pollfd[POLL_SOCKET].revents & POLLNVAL ||
|
||||
(notify >= 0 && pollfd[POLL_INOTIFY].revents & POLLNVAL)) {
|
||||
r = -EBADF;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0)
|
||||
(void) flush_fd(notify);
|
||||
|
||||
|
@ -541,6 +547,12 @@ int ask_password_tty(
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if ((pollfd[POLL_TTY].revents & POLLNVAL) ||
|
||||
(notify >= 0 && (pollfd[POLL_INOTIFY].revents & POLLNVAL))) {
|
||||
r = -EBADF;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (notify >= 0 && pollfd[POLL_INOTIFY].revents != 0 && keyname) {
|
||||
(void) flush_fd(notify);
|
||||
|
||||
|
@ -888,6 +900,13 @@ int ask_password_agent(
|
|||
goto finish;
|
||||
}
|
||||
|
||||
if (pollfd[FD_SOCKET].revents & POLLNVAL ||
|
||||
pollfd[FD_SIGNAL].revents & POLLNVAL ||
|
||||
(notify >= 0 && pollfd[FD_INOTIFY].revents & POLLNVAL)) {
|
||||
r = -EBADF;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (pollfd[FD_SIGNAL].revents & POLLIN) {
|
||||
r = -EINTR;
|
||||
goto finish;
|
||||
|
|
|
@ -218,10 +218,14 @@ static bool barrier_read(Barrier *b, int64_t comp) {
|
|||
uint64_t buf;
|
||||
int r;
|
||||
|
||||
r = poll(pfd, 2, -1);
|
||||
if (r < 0 && IN_SET(errno, EAGAIN, EINTR))
|
||||
continue;
|
||||
else if (r < 0)
|
||||
r = poll(pfd, ELEMENTSOF(pfd), -1);
|
||||
if (r < 0) {
|
||||
if (IN_SET(errno, EAGAIN, EINTR))
|
||||
continue;
|
||||
goto error;
|
||||
}
|
||||
if (pfd[0].revents & POLLNVAL ||
|
||||
pfd[1].revents & POLLNVAL)
|
||||
goto error;
|
||||
|
||||
if (pfd[1].revents) {
|
||||
|
|
|
@ -334,9 +334,10 @@ static int write_to_terminal(const char *tty, const char *message) {
|
|||
k = poll(&pollfd, 1, (end - t) / USEC_PER_MSEC);
|
||||
if (k < 0)
|
||||
return -errno;
|
||||
|
||||
if (k == 0)
|
||||
return -ETIME;
|
||||
if (pollfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
n = write(fd, p, left);
|
||||
if (n < 0) {
|
||||
|
|
|
@ -1048,10 +1048,14 @@ int varlink_wait(Varlink *v, usec_t timeout) {
|
|||
NULL);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (pfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
handle_revents(v, pfd.revents);
|
||||
|
||||
return r > 0 ? 1 : 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int varlink_get_fd(Varlink *v) {
|
||||
|
@ -1139,9 +1143,14 @@ int varlink_flush(Varlink *v) {
|
|||
.events = POLLOUT,
|
||||
};
|
||||
|
||||
if (poll(&pfd, 1, -1) < 0)
|
||||
r = poll(&pfd, 1, -1);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
assert(r > 0);
|
||||
if (pfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
handle_revents(v, pfd.revents);
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,9 @@ static int execute_s2h(const SleepConfig *sleep_config) {
|
|||
|
||||
tfd = safe_close(tfd);
|
||||
|
||||
if (FLAGS_SET(fds.revents, POLLNVAL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Invalid timer fd to sleep on?");
|
||||
|
||||
if (!FLAGS_SET(fds.revents, POLLIN)) /* We woke up before the alarm time, we are done. */
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -238,17 +238,19 @@ static int run(int argc, char *argv[]) {
|
|||
ts = timespec_store(&_ts, t);
|
||||
}
|
||||
|
||||
{
|
||||
struct pollfd p[3] = {
|
||||
{.fd = fd, .events = events_a },
|
||||
{.fd = STDIN_FILENO, .events = events_b & POLLIN },
|
||||
{.fd = STDOUT_FILENO, .events = events_b & POLLOUT },
|
||||
};
|
||||
struct pollfd p[3] = {
|
||||
{ .fd = fd, .events = events_a },
|
||||
{ .fd = STDIN_FILENO, .events = events_b & POLLIN },
|
||||
{ .fd = STDOUT_FILENO, .events = events_b & POLLOUT },
|
||||
};
|
||||
|
||||
r = ppoll(p, ELEMENTSOF(p), ts, NULL);
|
||||
}
|
||||
r = ppoll(p, ELEMENTSOF(p), ts, NULL);
|
||||
if (r < 0)
|
||||
return log_error_errno(errno, "ppoll() failed: %m");
|
||||
if (p[0].revents & POLLNVAL ||
|
||||
p[1].revents & POLLNVAL ||
|
||||
p[2].revents & POLLNVAL)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Invalid file descriptor to poll on?");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -395,6 +395,10 @@ static int process_and_watch_password_files(bool watch) {
|
|||
return -errno;
|
||||
}
|
||||
|
||||
if (pollfd[FD_SIGNAL].revents & POLLNVAL ||
|
||||
pollfd[FD_INOTIFY].revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
|
||||
if (pollfd[FD_INOTIFY].revents != 0)
|
||||
(void) flush_fd(notify);
|
||||
|
||||
|
|
|
@ -202,7 +202,12 @@ int settle_main(int argc, char *argv[], void *userdata) {
|
|||
return -ETIMEDOUT;
|
||||
|
||||
/* wake up when queue becomes empty */
|
||||
if (poll(&pfd, 1, MSEC_PER_SEC) > 0 && pfd.revents & POLLIN) {
|
||||
r = poll(&pfd, 1, MSEC_PER_SEC);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (pfd.revents & POLLNVAL)
|
||||
return -EBADF;
|
||||
if (r > 0 && pfd.revents & POLLIN) {
|
||||
r = udev_queue_flush(queue);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to flush queue: %m");
|
||||
|
|
|
@ -757,6 +757,8 @@ static int run(int argc, char *argv[]) {
|
|||
|
||||
if (poll(&pfd, 1, 0) < 0)
|
||||
return log_error_errno(errno, "Failed to test for POLLIN on listening socket: %m");
|
||||
if (FLAGS_SET(pfd.revents, POLLNVAL))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Listening socket dead?");
|
||||
|
||||
if (FLAGS_SET(pfd.revents, POLLIN)) {
|
||||
pid_t parent;
|
||||
|
|
Loading…
Reference in New Issue