Ticket #1562 (closed defect: fixed)

Opened 3 months ago

Last modified 2 months ago

sigsegv @ fdevent_get_handler - when congestion occurs, and file descriptor arrays is full.

Reported by: fdeletang Assigned to: jan
Priority: highest Milestone: 1.5.0
Component: core Version: 1.4.18
Severity: blocker Keywords: patch
Cc: Blocking:
Need Feedback: 0

Description

I'm experiencing segfaults when congestion occurs, at 800-850Mbps.

The crashes occurs here: lighttpd[1334]: segfault at 0000000c eip 0805ef46 esp bfc63e80 error 4

0x0805ef44 <fdevent_get_handler+20>:    je     0x805ef4f <fdevent_get_handler+31>
0x0805ef46 <fdevent_get_handler+22>:    cmp    0x8(%eax),%edx
0x0805ef49 <fdevent_get_handler+25>:    jne    0x805ef7c <fdevent_get_handler+76>
171         if (ev->fdarray[fd]->fd != fd) SEGFAULT();

I guess eax is ev->fdarray[fd], it's not NULL but it's not a valid pointer either, thus, trying to access ev->fdarray[fd]->fd makes lighty read from inexistent segments or segments without read permission.

So what's wrong ? Maybe fd is just an index out of the allocated array. Let's have a look on how it's being created.

fdevent.c:

 15 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
 19         ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));

server.c:

1076         if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {

and earlier in the same file:

 679                 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
 680                         log_error_write(srv, __FILE__, __LINE__,
 681                                         "ss", "couldn't get 'max filedescriptors'",
 682                                         strerror(errno));
 683                         return -1;
 684                 }
 685 
 686                 if (use_rlimit && srv->srvconf.max_fds) {
 687                         /* set rlimits */
 688 
 689                         rlim.rlim_cur = srv->srvconf.max_fds;
 690                         rlim.rlim_max = srv->srvconf.max_fds;
 691 
 692                         if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
 693                                 log_error_write(srv, __FILE__, __LINE__,
 694                                                 "ss", "couldn't set 'max filedescriptors'",
 695                                                 strerror(errno));
 696                                 return -1;
 697                         }
 698                 }


 700                 /* #372: solaris need some fds extra for devpoll */
 701                 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;

 827                         srv->max_fds = rlim.rlim_cur;

So, here's what's being done:

  • the process fetch the current configured rlimits and save it in rlim
  • if the configuration has a setting for max_fds, it override the one that's configured for the current task
  • The, the max_fds get decremented by 10 (solaris bugfix, yay)
  • and the allocation of the file descriptor array is being made using max_fds as size.

And here's what happen:

  • The system can give you more than max_fds file descriptors
  • fd > max_fds
  • sigsegv

Possible workarounds:

  • comment line 701 in server.c if you're not running solaris or
  • replace maxfds by maxfds + 10 in line 19 of fdevent.c or
  • fix this race condition ;-)

Attachments

Fix-372-and-1562.patch (1.2 kB) - added by stbuehler on 02/13/2008 02:38:55 PM.
Patch for 1.4 and 1.5

Change History

02/13/2008 02:25:13 PM changed by stbuehler

If i understood the #372 problem correctly, Solaris doesn't want to poll for rlim.cur fds, as one is used for the /dev/poll fd, and returns an error.

But it doesn't seem to matter if the dopoll.dp_nfds value is a little bit smaller - it is just the max number of events to be polled in one syscall.

So i think reducing the number dopoll.dp_nfds by one in fdevent_solaris_devpoll_poll should fix #372 and we can remove the previous "fix" for it to fix this bug (#1562).

02/13/2008 02:38:55 PM changed by stbuehler

  • attachment Fix-372-and-1562.patch added.

Patch for 1.4 and 1.5

02/13/2008 02:39:38 PM changed by stbuehler

  • keywords changed from fdevent_get_handler congestion file descriptor array full to patch.

02/20/2008 09:00:53 AM changed by Olaf van der Spek

Does this apply to 1.4.13 as well?

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=466663

02/20/2008 10:31:04 AM changed by stbuehler

Yes; #372 was "fixed" (i.e. introduced this bug) in [853], which was between 1.4.7 and 1.4.8.

02/20/2008 10:37:16 AM changed by Olaf van der Spek

Doesn't this allow for an easy DoS attack?

02/21/2008 07:49:39 PM changed by Olaf van der Spek

  • priority changed from high to highest.
  • severity changed from major to blocker.

It's remotely exploitable...

02/26/2008 04:28:15 PM changed by stbuehler

  • status changed from new to closed.
  • resolution set to fixed.

Fixed in [2082]


Add/Change #1562 (sigsegv @ fdevent_get_handler - when congestion occurs, and file descriptor arrays is full.)




Change Properties
Action