[multiple] open target file earlier in some cases

open target file earlier in some cases to validate readability
This commit is contained in:
Glenn Strauss 2019-04-29 20:20:47 -04:00
parent 470a692211
commit 44156bbe81
3 changed files with 55 additions and 30 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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 ",