aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2023-01-13 10:40:52 +1300
committerThomas Munro <tmunro@postgresql.org>2023-01-13 11:02:00 +1300
commit8a98523a542f0fb6fa19c071922776dac7d45d36 (patch)
treeec640b253ef55f7a58c59bb8e9bf45ac09bebf14 /src
parent4dc3f94fae3de3f19b5c7dd507beac0216b0cde9 (diff)
downloadpostgresql-8a98523a542f0fb6fa19c071922776dac7d45d36.tar.gz
postgresql-8a98523a542f0fb6fa19c071922776dac7d45d36.zip
Fix WaitEventSetWait() buffer overrun.
The WAIT_USE_EPOLL and WAIT_USE_KQUEUE implementations of WaitEventSetWaitBlock() confused the size of their internal buffer with the size of the caller's output buffer, and could ask the kernel for too many events. In fact the set of events retrieved from the kernel needs to be able to fit in both buffers, so take the smaller of the two. The WAIT_USE_POLL and WAIT_USE WIN32 implementations didn't have this confusion. This probably didn't come up before because we always used the same number in both places, but commit 7389aad6 calculates a dynamic size at construction time, while using MAXLISTEN for its output event buffer on the stack. That seems like a reasonable thing to want to do, so consider this to be a pre-existing bug worth fixing. As discovered by valgrind on skink. Back-patch to all supported releases for epoll, and to release 13 for the kqueue part, which copied the incorrect epoll code. Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/901504.1673504836%40sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/ipc/latch.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index eb3a569aae1..8bdb5497aa4 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -1487,7 +1487,7 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* Sleep */
rc = epoll_wait(set->epoll_fd, set->epoll_ret_events,
- nevents, cur_timeout);
+ Min(nevents, set->nevents_space), cur_timeout);
/* Check return code */
if (rc < 0)
@@ -1647,7 +1647,8 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
/* Sleep */
rc = kevent(set->kqueue_fd, NULL, 0,
- set->kqueue_ret_events, nevents,
+ set->kqueue_ret_events,
+ Min(nevents, set->nevents_space),
timeout_p);
/* Check return code */