Browse Source

[mod_compress] use mmap and trap SIGBUS (#2666, fixes #1879)

use mmap and trap SIGBUS in mod_compress
(if lighttpd build with --enable-mmap)

mod_compress has not used mmap since Feb 2012 (see #2391)

x-ref:
  "Lighttpd 1.4.20 Crash (SIGBUS in mod_compress)"
  https://redmine.lighttpd.net/issues/1879
  "Crash SIGBUS"
  https://redmine.lighttpd.net/issues/2391
  "handle filesystems without mmap() support"
  https://redmine.lighttpd.net/issues/2666

github: closes #56
personal/stbuehler/mod-csrf-old
Glenn Strauss 6 years ago
parent
commit
c9b56735b8
  1. 102
      src/mod_compress.c

102
src/mod_compress.c

@ -36,7 +36,22 @@
# include <bzlib.h>
#endif
#if defined HAVE_SYS_MMAN_H && defined HAVE_MMAP && defined ENABLE_MMAP
#define USE_MMAP
#include "sys-mmap.h"
#include <setjmp.h>
#include <signal.h>
static volatile int sigbus_jmp_valid;
static sigjmp_buf sigbus_jmp;
static void sigbus_handler(int sig) {
UNUSED(sig);
if (sigbus_jmp_valid) siglongjmp(sigbus_jmp, 1);
log_failed_assert(__FILE__, __LINE__, "SIGBUS");
}
#endif
/* request: accept-encoding */
#define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
@ -420,6 +435,9 @@ static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_dat
static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
int ifd, ofd;
int ret;
#ifdef USE_MMAP
volatile int mapped = 0;/* quiet warning: might be clobbered by 'longjmp' */
#endif
void *start;
const char *filename = fn->ptr;
ssize_t r;
@ -500,22 +518,30 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
}
#ifdef USE_MMAP
if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
close(ofd);
close(ifd);
if (MAP_FAILED != (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
mapped = 1;
signal(SIGBUS, sigbus_handler);
sigbus_jmp_valid = 1;
if (0 != sigsetjmp(sigbus_jmp, 1)) {
sigbus_jmp_valid = 0;
log_error_write(srv, __FILE__, __LINE__, "sbd", "SIGBUS in mmap:",
fn, ifd);
munmap(start, sce->st.st_size);
close(ofd);
close(ifd);
/* Remove the incomplete cache file, so that later hits aren't served from it */
if (-1 == unlink(p->ofn->ptr)) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
}
/* Remove the incomplete cache file, so that later hits aren't served from it */
if (-1 == unlink(p->ofn->ptr)) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "unlinking incomplete cachefile", p->ofn, "failed:", strerror(errno));
return -1;
}
return -1;
}
#else
start = malloc(sce->st.st_size);
if (NULL == start || sce->st.st_size != read(ifd, start, sce->st.st_size)) {
} else
#endif /* FIXME: might attempt to read very large file completely into memory; see compress.max-filesize config option */
if (NULL == (start = malloc(sce->st.st_size)) || sce->st.st_size != read(ifd, start, sce->st.st_size)) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "reading", fn, "failed", strerror(errno));
close(ofd);
@ -529,7 +555,6 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
return -1;
}
#endif
ret = -1;
switch(type) {
@ -562,10 +587,12 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
}
#ifdef USE_MMAP
munmap(start, sce->st.st_size);
#else
free(start);
if (mapped) {
sigbus_jmp_valid = 0;
munmap(start, sce->st.st_size);
} else
#endif
free(start);
close(ofd);
close(ifd);
@ -587,6 +614,9 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
int ifd;
int ret = -1;
#ifdef USE_MMAP
volatile int mapped = 0;/* quiet warning: might be clobbered by 'longjmp' */
#endif
void *start;
/* overflow */
@ -607,22 +637,29 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p,
}
#ifdef USE_MMAP
if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
close(ifd);
return -1;
}
#else
start = malloc(sce->st.st_size);
if (NULL == start || sce->st.st_size != read(ifd, start, sce->st.st_size)) {
if (MAP_FAILED != (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
mapped = 1;
signal(SIGBUS, sigbus_handler);
sigbus_jmp_valid = 1;
if (0 != sigsetjmp(sigbus_jmp, 1)) {
sigbus_jmp_valid = 0;
log_error_write(srv, __FILE__, __LINE__, "sbd", "SIGBUS in mmap:",
fn, ifd);
munmap(start, sce->st.st_size);
close(ifd);
return -1;
}
} else
#endif /* FIXME: might attempt to read very large file completely into memory; see compress.max-filesize config option */
if (NULL == (start = malloc(sce->st.st_size)) || sce->st.st_size != read(ifd, start, sce->st.st_size)) {
log_error_write(srv, __FILE__, __LINE__, "sbss", "reading", fn, "failed", strerror(errno));
close(ifd);
free(start);
return -1;
}
#endif
switch(type) {
#ifdef USE_ZLIB
@ -646,10 +683,13 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p,
}
#ifdef USE_MMAP
munmap(start, sce->st.st_size);
#else
free(start);
if (mapped) {
sigbus_jmp_valid = 0;
munmap(start, sce->st.st_size);
} else
#endif
free(start);
close(ifd);
if (ret != 0) return -1;

Loading…
Cancel
Save