lighttpd: prevent invalid fdarray access

The fd event handling uses the fd to directly access the array slot and
expects the fds to be contiguous and capped.

Since the returned fds from our libc were much larger than expected,
because the libc itself consumes multiple fds when managing sockets,
using the fd in this manner leads to memory corruption.

This commit limits the maxfds to 63 and always allocates 1024 slots
in the fd-array.

Fixes #5320.
This commit is contained in:
Josef Söntgen 2024-08-13 13:56:20 +02:00 committed by Christian Helmuth
parent 3b5ea97e8f
commit 83ddc41d63
3 changed files with 34 additions and 2 deletions

View File

@ -1 +1 @@
bbd4b02e545e2ba95fffddf5411c44dbbdb75efe
a603d9dcba885cc5a3f264a4a21ea16294523d84

View File

@ -6,4 +6,4 @@ URL(lighttpd) := http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-$
SHA(lighttpd) := 816cbec71e8d02d874f1d5c798d76d091a76d5acbeb6e017ba76aeb4263d6995
DIR(lighttpd) := src/app/lighttpd
PATCHES := $(addprefix src/app/lighttpd/,fd_cloexec.patch mod_dirlisting.patch mod_webdav.patch no_o_nonblock.patch)
PATCHES := $(addprefix src/app/lighttpd/,fd_cloexec.patch invalid_fdarray_access.patch mod_dirlisting.patch mod_webdav.patch no_o_nonblock.patch)

View File

@ -0,0 +1,32 @@
The lighttpd code expects continous and constrained fd numbering as it
is directly used for accessing array elements. As our libc consumes
itself fds internally, e.g. socket_fs, overallocate the fdarray and add
check that limits used fds.
--- src/app/lighttpd/src/fdevent_impl.c
+++ src/app/lighttpd/src/fdevent_impl.c
@@ -188,6 +188,15 @@
maxfds = (uint32_t)FD_SETSIZE - 200;
}
#endif
+
+ if (maxfds > 63) {
+ maxfds = 63;
+ log_error(errh, __FILE__, __LINE__,
+ "%s: limit maxfds to %u to prevent "
+ "invalid array access",
+ __func__, maxfds);
+ }
+
*max_fds = (int)maxfds;
++maxfds; /*(+1 for event-handler fd)*/
@@ -195,7 +204,8 @@
ev->errh = errh;
ev->cur_fds = cur_fds;
ev->event_handler = event_handler;
- ev->fdarray = ck_calloc(maxfds, sizeof(*ev->fdarray));
+ /* over allocate fdarray and rely on the maxfds check above */
+ ev->fdarray = ck_calloc(1024, sizeof(*ev->fdarray));
ev->maxfds = maxfds;
switch(type) {