summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2019-04-29 20:20:47 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2019-05-04 13:48:22 -0400
commit44156bbe81be274a41725ab35ecc91f609caa5cf (patch)
tree069c5b6ff2e4f0c9a62ceeaa32b7e53df9c19979
parent470a692211a31627095fd2db1924df961139388c (diff)
downloadlighttpd1.4-44156bbe81be274a41725ab35ecc91f609caa5cf.tar.gz
lighttpd1.4-44156bbe81be274a41725ab35ecc91f609caa5cf.zip
[multiple] open target file earlier in some cases
open target file earlier in some cases to validate readability
-rw-r--r--src/http-header-glue.c24
-rw-r--r--src/mod_compress.c44
-rw-r--r--src/mod_ssi.c17
3 files changed, 55 insertions, 30 deletions
diff --git a/src/http-header-glue.c b/src/http-header-glue.c
index 3885127b..3f4957a1 100644
--- a/src/http-header-glue.c
+++ b/src/http-header-glue.c
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <fcntl.h>
#include <time.h>
@@ -468,6 +469,17 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
return;
}
+ /*(Note: O_NOFOLLOW affects only the final path segment,
+ * the target file, not any intermediate symlinks along path)*/
+ const int fd = fdevent_open_cloexec(path->ptr, con->conf.follow_symlink, O_RDONLY, 0);
+ if (fd < 0) {
+ con->http_status = (errno == ENOENT) ? 404 : 403;
+ if (con->conf.log_request_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "file open failed:", path, strerror(errno));
+ }
+ return;
+ }
+
/* mod_compress might set several data directly, don't overwrite them */
/* set response content-type, if not set already */
@@ -510,6 +522,7 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
}
if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
+ close(fd);
return;
}
}
@@ -557,6 +570,7 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
if (0 == http_response_parse_range(srv, con, path, sce, range->ptr+6)) {
con->http_status = 206;
}
+ close(fd);
return;
}
}
@@ -566,12 +580,10 @@ void http_response_send_file (server *srv, connection *con, buffer *path) {
/* we add it here for all requests
* the HEAD request will drop it afterwards again
*/
- if (0 == sce->st.st_size || 0 == http_chunk_append_file(srv, con, path)) {
- con->http_status = 200;
- con->file_finished = 1;
- } else {
- con->http_status = 403;
- }
+
+ http_chunk_append_file_fd(srv, con, path, fd, sce->st.st_size);
+ con->http_status = 200;
+ con->file_finished = 1;
}
diff --git a/src/mod_compress.c b/src/mod_compress.c
index 45f5579e..ec475d57 100644
--- a/src/mod_compress.c
+++ b/src/mod_compress.c
@@ -467,14 +467,13 @@ static void mod_compress_note_ratio(server *srv, connection *con, off_t in, off_
UNUSED(srv);
}
-static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
- int ifd, ofd;
+static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, int ifd, buffer *fn, stat_cache_entry *sce, int type) {
+ int 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;
stat_cache_entry *sce_ofn;
ssize_t r;
@@ -550,18 +549,6 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
#if 0
log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
#endif
- if (-1 == (ifd = fdevent_open_cloexec(filename, con->conf.follow_symlink, O_RDONLY, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
-
- close(ofd);
-
- /* 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;
- }
#ifdef USE_MMAP
if (MAP_FAILED != (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))
@@ -663,8 +650,7 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu
return 0;
}
-static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, buffer *fn, stat_cache_entry *sce, int type) {
- int ifd;
+static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, int ifd, buffer *fn, stat_cache_entry *sce, int type) {
int ret = -1;
#ifdef USE_MMAP
volatile int mapped = 0;/* quiet warning: might be clobbered by 'longjmp' */
@@ -685,9 +671,9 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p,
return -1;
}
- if (-1 == (ifd = fdevent_open_cloexec(fn->ptr, con->conf.follow_symlink, O_RDONLY, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
-
+ if (-1 == ifd) {
+ /* not called; call exists to de-optimize and avoid "clobbered by 'longjmp'" compiler warning */
+ log_error_write(srv, __FILE__, __LINE__, "s", "");
return -1;
}
@@ -942,6 +928,13 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
return HANDLER_GO_ON;
}
+ const int fd = fdevent_open_cloexec(con->physical.path->ptr, con->conf.follow_symlink, O_RDONLY, 0);
+ if (fd < 0) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening plain-file", con->physical.path, "failed", strerror(errno));
+ return HANDLER_GO_ON;
+ }
+
mtime = strftime_cache_get(srv, sce->st.st_mtime);
/* try matching original etag of uncompressed version */
@@ -951,6 +944,7 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
http_header_response_set(con, HTTP_HEADER_LAST_MODIFIED, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
http_header_response_set(con, HTTP_HEADER_ETAG, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
+ close(fd);
return HANDLER_FINISHED;
}
}
@@ -989,17 +983,23 @@ PHYSICALPATH_FUNC(mod_compress_physical) {
if (use_etag) {
http_header_response_set(con, HTTP_HEADER_ETAG, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
}
+ close(fd);
return HANDLER_FINISHED;
}
/* deflate it */
if (use_etag && !buffer_string_is_empty(p->conf.compress_cache_dir)) {
- if (0 != deflate_file_to_file(srv, con, p, con->physical.path, sce, compression_type))
+ if (0 != deflate_file_to_file(srv, con, p, fd, con->physical.path, sce, compression_type)) {
+ close(fd);
return HANDLER_GO_ON;
+ }
} else {
- if (0 != deflate_file_to_buffer(srv, con, p, con->physical.path, sce, compression_type))
+ if (0 != deflate_file_to_buffer(srv, con, p, fd, con->physical.path, sce, compression_type)) {
+ close(fd);
return HANDLER_GO_ON;
+ }
}
+ close(fd);
http_header_response_set(con, HTTP_HEADER_CONTENT_ENCODING, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
http_header_response_set(con, HTTP_HEADER_LAST_MODIFIED, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
if (use_etag) {
diff --git a/src/mod_ssi.c b/src/mod_ssi.c
index eced7cfe..eefd2944 100644
--- a/src/mod_ssi.c
+++ b/src/mod_ssi.c
@@ -5,6 +5,7 @@
#include "log.h"
#include "buffer.h"
#include "http_header.h"
+#include "stat_cache.h"
#include "plugin.h"
@@ -584,7 +585,13 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
}
}
- if (0 == stat(p->stat_fn->ptr, &stb)) {
+ if (!con->conf.follow_symlink
+ && 0 != stat_cache_path_contains_symlink(srv, p->stat_fn)) {
+ break;
+ }
+
+ int fd = stat_cache_open_rdonly_fstat(p->stat_fn, &stb, con->conf.follow_symlink);
+ if (fd > 0) {
time_t t = stb.st_mtime;
switch (ssicmd) {
@@ -619,7 +626,8 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
if (file_path || 0 == p->conf.ssi_recursion_max) {
/* don't process if #include file="..." is used */
- chunkqueue_append_file(con->write_queue, p->stat_fn, 0, stb.st_size);
+ chunkqueue_append_file_fd(con->write_queue, p->stat_fn, fd, 0, stb.st_size);
+ fd = -1;
} else {
buffer *upsave, *ppsave, *prpsave;
@@ -649,6 +657,9 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
con->uri.path = con->physical.rel_path = buffer_init_buffer(srv->tmp_buf);
+ close(fd);
+ fd = -1;
+
/*(ignore return value; muddle along as best we can if error occurs)*/
++p->ssi_recursion_depth;
mod_ssi_process_file(srv, con, p, &stb);
@@ -665,6 +676,8 @@ static int process_ssi_stmt(server *srv, connection *con, handler_ctx *p, const
break;
}
+
+ if (fd > 0) close(fd);
} else {
log_error_write(srv, __FILE__, __LINE__, "sbs",
"ssi: stating failed ",