Browse Source

[core] pass conf.follow_symlink in more places

personal/stbuehler/ci-build
Glenn Strauss 3 years ago
parent
commit
37bd124ae4
  1. 3
      src/chunk.c
  2. 47
      src/fdevent.c
  3. 4
      src/fdevent.h
  4. 2
      src/gw_backend.c
  5. 2
      src/http_chunk.c
  6. 4
      src/mod_cgi.c
  7. 2
      src/mod_cml_lua.c
  8. 2
      src/mod_deflate.c
  9. 4
      src/mod_webdav.c
  10. 2
      src/rand.c
  11. 4
      src/server.c
  12. 22
      src/stat_cache.c
  13. 2
      src/stat_cache.h

3
src/chunk.c

@ -807,7 +807,8 @@ int chunkqueue_open_file_chunk(server *srv, chunkqueue *cq) {
toSend = c->file.length - c->offset;
if (-1 == c->file.fd) {
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, O_RDONLY, 0))) {
/* (permit symlinks; should already have been checked. However, TOC-TOU remains) */
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, 1, O_RDONLY, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ssb", "open failed:", strerror(errno), c->mem);
return -1;
}

47
src/fdevent.c

@ -484,15 +484,38 @@ int fdevent_socket_nb_cloexec(int domain, int type, int protocol) {
return fd;
}
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
/*(O_NOFOLLOW is not handled here)*/
/*(Note: O_NOFOLLOW affects only the final path segment, the target file,
* not any intermediate symlinks along the path)*/
int fdevent_open_cloexec(const char *pathname, int flags, mode_t mode) {
/* O_CLOEXEC handled further below, if defined) */
#ifdef O_NONBLOCK
#define FDEVENT_O_FLAGS \
(O_BINARY | O_LARGEFILE | O_NOCTTY | O_NONBLOCK)
#else
#define FDEVENT_O_FLAGS \
(O_BINARY | O_LARGEFILE | O_NOCTTY )
#endif
int fdevent_open_cloexec(const char *pathname, int symlinks, int flags, mode_t mode) {
if (!symlinks) flags |= O_NOFOLLOW;
#ifdef O_CLOEXEC
return open(pathname, flags | O_CLOEXEC | O_NOCTTY, mode);
return open(pathname, flags | O_CLOEXEC | FDEVENT_O_FLAGS, mode);
#else
int fd = open(pathname, flags | O_NOCTTY, mode);
int fd = open(pathname, flags | FDEVENT_O_FLAGS, mode);
#ifdef FD_CLOEXEC
if (fd != -1)
force_assert(-1 != fcntl(fd, F_SETFD, FD_CLOEXEC));
@ -504,14 +527,14 @@ int fdevent_open_cloexec(const char *pathname, int flags, mode_t mode) {
int fdevent_open_devnull(void) {
#if defined(_WIN32)
return fdevent_open_cloexec("nul", O_RDWR, 0);
return fdevent_open_cloexec("nul", 0, O_RDWR, 0);
#else
return fdevent_open_cloexec("/dev/null", O_RDWR, 0);
return fdevent_open_cloexec("/dev/null", 0, O_RDWR, 0);
#endif
}
int fdevent_open_dirname(char *path) {
int fdevent_open_dirname(char *path, int symlinks) {
/*(handle special cases of no dirname or dirname is root directory)*/
char * const c = strrchr(path, '/');
const char * const dname = (NULL != c ? c == path ? "/" : path : ".");
@ -521,7 +544,7 @@ int fdevent_open_dirname(char *path) {
flags |= O_DIRECTORY;
#endif
if (NULL != c) *c = '\0';
dfd = fdevent_open_cloexec(dname, flags, 0);
dfd = fdevent_open_cloexec(dname, symlinks, flags, 0);
if (NULL != c) *c = '/';
return dfd;
}
@ -861,14 +884,10 @@ static int fdevent_open_logger_pipe(const char *logger) {
}
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
int fdevent_open_logger(const char *logger) {
if (logger[0] != '|') {
int flags = O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE;
return fdevent_open_cloexec(logger, flags, 0644);
if (logger[0] != '|') { /*(permit symlinks)*/
int flags = O_APPEND | O_WRONLY | O_CREAT;
return fdevent_open_cloexec(logger, 1, flags, 0644);
}
else {
return fdevent_open_logger_pipe(logger+1); /*(skip the '|')*/

4
src/fdevent.h

@ -79,14 +79,14 @@ int fdevent_fcntl_set_nb_cloexec(fdevents *ev, int fd);
int fdevent_fcntl_set_nb_cloexec_sock(fdevents *ev, int fd);
int fdevent_socket_cloexec(int domain, int type, int protocol);
int fdevent_socket_nb_cloexec(int domain, int type, int protocol);
int fdevent_open_cloexec(const char *pathname, int flags, mode_t mode);
int fdevent_open_cloexec(const char *pathname, int symlinks, int flags, mode_t mode);
struct sockaddr;
int fdevent_accept_listenfd(int listenfd, struct sockaddr *addr, size_t *addrlen);
char ** fdevent_environ(void);
int fdevent_open_devnull(void);
int fdevent_open_dirname(char *path);
int fdevent_open_dirname(char *path, int symlinks);
int fdevent_set_stdin_stdout_stderr(int fdin, int fdout, int fderr);
pid_t fdevent_fork_execve(const char *name, char *argv[], char *envp[], int fdin, int fdout, int fderr, int dfd);
int fdevent_open_logger(const char *logger);

2
src/gw_backend.c

@ -562,7 +562,7 @@ static int gw_spawn_connection(server *srv, gw_host *host, gw_proc *proc, int de
env.ptr[env.used] = NULL;
}
dfd = fdevent_open_dirname(host->args.ptr[0]);
dfd = fdevent_open_dirname(host->args.ptr[0], 1); /* permit symlinks */
if (-1 == dfd) {
log_error_write(srv, __FILE__, __LINE__, "sss",
"open dirname failed:", strerror(errno),

2
src/http_chunk.c

@ -41,7 +41,7 @@ static int http_chunk_append_file_open_fstat(server *srv, connection *con, buffe
if (HANDLER_ERROR == stat_cache_get_entry(srv, con, fn, &sce)) return -1;
}
return stat_cache_open_rdonly_fstat(srv, con, fn, st);
return stat_cache_open_rdonly_fstat(fn, st, con->conf.follow_symlink);
}
static void http_chunk_append_file_fd_range(server *srv, connection *con, buffer *fn, int fd, off_t offset, off_t len) {

4
src/mod_cgi.c

@ -551,7 +551,7 @@ static ssize_t cgi_write_file_chunk_mmap(server *srv, connection *con, int fd, c
/*(simplified from chunk.c:chunkqueue_open_file_chunk())*/
UNUSED(con);
if (-1 == c->file.fd) {
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, O_RDONLY, 0))) {
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, con->conf.follow_symlink, O_RDONLY, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ssb", "open failed:", strerror(errno), c->mem);
return -1;
}
@ -804,7 +804,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, handler_
args[i ] = NULL;
}
dfd = fdevent_open_dirname(con->physical.path->ptr);
dfd = fdevent_open_dirname(con->physical.path->ptr, con->conf.follow_symlink);
if (-1 == dfd) {
log_error_write(srv, __FILE__, __LINE__, "ssb", "open dirname failed:", strerror(errno), con->physical.path);
}

2
src/mod_cml_lua.c

@ -236,7 +236,7 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
buffer_copy_string(b, lua_tostring(L, -1));
}
fd = stat_cache_open_rdonly_fstat(srv, con, b, &st);
fd = stat_cache_open_rdonly_fstat(b, &st, con->conf.follow_symlink);
if (fd < 0) {
/* stat failed */

2
src/mod_deflate.c

@ -732,7 +732,7 @@ static int mod_deflate_file_chunk(server *srv, connection *con, handler_ctx *hct
#endif
if (-1 == c->file.fd) { /* open the file if not already open */
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, O_RDONLY, 0))) {
if (-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, con->conf.follow_symlink, O_RDONLY, 0))) {
log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->mem, strerror(errno));
return -1;

4
src/mod_webdav.c

@ -1128,7 +1128,7 @@ static int webdav_parse_chunkqueue(server *srv, connection *con, handler_ctx *hc
data = c->file.mmap.start + c->offset;
} else {
if (-1 == c->file.fd && /* open the file if not already open */
-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, O_RDONLY, 0))) {
-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, con->conf.follow_symlink, O_RDONLY, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
return -1;
@ -1838,7 +1838,7 @@ static handler_t mod_webdav_put(server *srv, connection *con, plugin_data *p, ha
data = c->file.mmap.start + c->offset;
} else {
if (-1 == c->file.fd && /* open the file if not already open */
-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, O_RDONLY, 0))) {
-1 == (c->file.fd = fdevent_open_cloexec(c->mem->ptr, con->conf.follow_symlink, O_RDONLY, 0))) {
log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
close(fd);
return HANDLER_ERROR;

2
src/rand.c

@ -106,7 +106,7 @@ static int li_rand_device_bytes (unsigned char *buf, int num)
for (unsigned int u = 0; u < sizeof(devices)/sizeof(devices[0]); ++u) {
/*(some systems might have symlink to another device; omit O_NOFOLLOW)*/
int fd = fdevent_open_cloexec(devices[u], O_RDONLY, 0);
int fd = fdevent_open_cloexec(devices[u], 0, O_RDONLY, 0);
if (fd >= 0) {
ssize_t rd = 0;
#ifdef RNDGETENTCNT

4
src/server.c

@ -1266,7 +1266,7 @@ static int server_main (server * const srv, int argc, char **argv) {
/* open pid file BEFORE chroot */
if (-2 == pid_fd) pid_fd = -1; /*(initial startup state)*/
if (-1 == pid_fd && !buffer_string_is_empty(srv->srvconf.pid_file)) {
if (-1 == (pid_fd = fdevent_open_cloexec(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
if (-1 == (pid_fd = fdevent_open_cloexec(srv->srvconf.pid_file->ptr, 0, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
struct stat st;
if (errno != EEXIST) {
log_error_write(srv, __FILE__, __LINE__, "sbs",
@ -1285,7 +1285,7 @@ static int server_main (server * const srv, int argc, char **argv) {
return -1;
}
if (-1 == (pid_fd = fdevent_open_cloexec(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
if (-1 == (pid_fd = fdevent_open_cloexec(srv->srvconf.pid_file->ptr, 0, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
log_error_write(srv, __FILE__, __LINE__, "sbs",
"opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
return -1;

22
src/stat_cache.c

@ -770,27 +770,10 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_
return HANDLER_GO_ON;
}
int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, struct stat *st) {
int stat_cache_open_rdonly_fstat (buffer *name, struct stat *st, int symlinks) {
/*(Note: O_NOFOLLOW affects only the final path segment, the target file,
* not any intermediate symlinks along the path)*/
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK 0
#endif
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
const int oflags = O_BINARY | O_LARGEFILE | O_NOCTTY | O_NONBLOCK
| (con->conf.follow_symlink ? 0 : O_NOFOLLOW);
const int fd = fdevent_open_cloexec(name->ptr, O_RDONLY | oflags, 0);
const int fd = fdevent_open_cloexec(name->ptr, symlinks, O_RDONLY, 0);
if (fd >= 0) {
if (0 == fstat(fd, st)) {
return fd;
@ -798,7 +781,6 @@ int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, st
close(fd);
}
}
UNUSED(srv); /*(might log_error_write(srv, ...) in the future)*/
return -1;
}

2
src/stat_cache.h

@ -44,7 +44,7 @@ const buffer * stat_cache_mimetype_by_ext(const connection *con, const char *nam
const buffer * stat_cache_content_type_get(server *srv, connection *con, const buffer *name, stat_cache_entry *sce);
const buffer * stat_cache_etag_get(stat_cache_entry *sce, etag_flags_t flags);
handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_cache_entry **sce);
int stat_cache_open_rdonly_fstat (server *srv, connection *con, buffer *name, struct stat *st);
int stat_cache_open_rdonly_fstat (buffer *name, struct stat *st, int symlinks);
int stat_cache_trigger_cleanup(server *srv);
#endif

Loading…
Cancel
Save