diff -Naur a/keepalived/core/pidfile.c b/keepalived/core/pidfile.c --- a/keepalived/core/pidfile.c 2019-02-15 01:01:32.886542487 +0530 +++ b/keepalived/core/pidfile.c 2019-02-15 01:01:09.414541360 +0530 @@ -54,7 +54,7 @@ pidfile_write(const char *pid_file, int pid) { FILE *pidfile = NULL; - int pidfd = creat(pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int pidfd = open(pid_file, O_NOFOLLOW | O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (pidfd != -1) pidfile = fdopen(pidfd, "w"); if (!pidfile) { diff -Naur a/keepalived/vrrp/vrrp_dbus.c b/keepalived/vrrp/vrrp_dbus.c --- a/keepalived/vrrp/vrrp_dbus.c 2019-02-15 01:01:32.886542487 +0530 +++ b/keepalived/vrrp/vrrp_dbus.c 2019-02-15 01:04:31.058551041 +0530 @@ -551,7 +551,7 @@ size_t length; gchar *ret = NULL; - f = fopen(filepath, "rb"); + f = fopen(filepath, "r"); if (f) { fseek(f, 0, SEEK_END); length = (size_t)ftell(f); diff -Naur a/keepalived/vrrp/vrrp_print.c b/keepalived/vrrp/vrrp_print.c --- a/keepalived/vrrp/vrrp_print.c 2019-02-15 01:01:32.886542487 +0530 +++ b/keepalived/vrrp/vrrp_print.c 2019-02-15 01:01:09.410541360 +0530 @@ -34,6 +34,7 @@ #include "keepalived_netlink.h" #include "rttables.h" #include "logger.h" +#include "utils.h" #include #include @@ -350,7 +351,7 @@ vrrp_print_data(void) { FILE *file; - file = fopen ("/tmp/keepalived.data","w"); + file = fopen_safe("/tmp/keepalived.data","w"); if (!file) { log_message(LOG_INFO, "Can't open /tmp/keepalived.data (%d: %s)", @@ -374,7 +375,9 @@ vrrp_print_stats(void) { FILE *file; - file = fopen ("/tmp/keepalived.stats","w"); + file = fopen_safe("/tmp/keepalived.stats","w"); + element e; + vrrp_t *vrrp; if (!file) { log_message(LOG_INFO, "Can't open /tmp/keepalived.stats (%d: %s)", @@ -382,19 +385,13 @@ return; } - list l = vrrp_data->vrrp; - element e; - vrrp_t *vrrp; - - for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) { - vrrp = ELEMENT_DATA(e); + LIST_FOREACH(vrrp_data->vrrp, vrrp, e) { fprintf(file, "VRRP Instance: %s\n", vrrp->iname); fprintf(file, " Advertisements:\n"); fprintf(file, " Received: %" PRIu64 "\n", vrrp->stats->advert_rcvd); fprintf(file, " Sent: %d\n", vrrp->stats->advert_sent); fprintf(file, " Became master: %d\n", vrrp->stats->become_master); - fprintf(file, " Released master: %d\n", - vrrp->stats->release_master); + fprintf(file, " Released master: %d\n", vrrp->stats->release_master); fprintf(file, " Packet Errors:\n"); fprintf(file, " Length: %" PRIu64 "\n", vrrp->stats->packet_len_err); fprintf(file, " TTL: %" PRIu64 "\n", vrrp->stats->ip_ttl_err); diff -Naur a/lib/list.h b/lib/list.h --- a/lib/list.h 2019-02-15 01:01:55.538543574 +0530 +++ b/lib/list.h 2019-02-15 01:17:13.926587668 +0530 @@ -51,6 +51,7 @@ #define LIST_ISEMPTY(L) ((L) == NULL || ((L)->head == NULL && (L)->tail == NULL)) #define LIST_EXISTS(L) ((L) != NULL) #define LIST_SIZE(V) ((V)->count) +#define LIST_FOREACH(L,V,E) for ((E) = ((L) ? LIST_HEAD(L) : NULL); (E) && ((V) = ELEMENT_DATA(E), 1); ELEMENT_NEXT(E)) /* Prototypes */ extern list alloc_list(void (*free_func) (void *), void (*dump_func) (void *)); diff -Naur a/lib/memory.c b/lib/memory.c --- a/lib/memory.c 2019-02-15 01:01:55.538543574 +0530 +++ b/lib/memory.c 2019-02-15 01:01:20.114541874 +0530 @@ -441,7 +441,7 @@ } snprintf(log_name, log_name_len, "/tmp/%s_mem.%d.log", prog_name, getpid()); - log_op = fopen(log_name, "a"); + log_op = fopen_safe(log_name, "a"); if (log_op == NULL) { log_message(LOG_INFO, "Unable to open %s for appending", log_name); log_op = stderr; diff -Naur a/lib/parser.c b/lib/parser.c --- a/lib/parser.c 2019-02-15 01:01:55.538543574 +0530 +++ b/lib/parser.c 2019-02-15 01:01:20.114541874 +0530 @@ -153,12 +153,12 @@ { unsigned int i; keyword_t *keyword_vec; - char file_name[21]; + char file_name[22]; if (!level) { sprintf(file_name, "/tmp/keywords.%d", getpid()); snprintf(file_name, sizeof(file_name), "/tmp/keywords.%d", getpid()); - fp = fopen(file_name, "w"); + fp = fopen_safe(file_name, "w"); if (!fp) return; } diff -Naur a/lib/utils.c b/lib/utils.c --- a/lib/utils.c 2019-02-15 01:01:55.538543574 +0530 +++ b/lib/utils.c 2019-02-15 01:01:20.114541874 +0530 @@ -89,7 +89,7 @@ void write_stacktrace(const char *file_name) { - int fd = open(file_name, O_WRONLY | O_APPEND | O_CREAT, 0644); + int fd = open(file_name, O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); void *buffer[100]; int nptrs; @@ -518,6 +518,47 @@ return (*str1 == 0 && *str2 == 0); } +/* We need to use O_NOFOLLOW if opening a file for write, so that a non privileged user can't + * create a symbolic link from the path to a system file and cause a system file to be overwritten. */ +FILE *fopen_safe(const char *path, const char *mode) +{ + int fd; + FILE *file; + int flags = O_NOFOLLOW | O_CREAT; + + if (mode[0] == 'r') + return fopen(path, mode); + + if (mode[0] != 'a' && mode[0] != 'w') + return NULL; + + if (mode[1] && + (mode[1] != '+' || mode[2])) + return NULL; + + if (mode[0] == 'w') + flags |= O_TRUNC; + else + flags |= O_APPEND; + + if (mode[1]) + flags |= O_RDWR; + else + flags |= O_WRONLY; + + fd = open(path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (fd == -1) + return NULL; + + file = fdopen (fd, "w"); + if (!file) { + close(fd); + return NULL; + } + + return file; +} + void set_std_fd(int force) { diff -Naur a/lib/utils.h b/lib/utils.h --- a/lib/utils.h 2019-02-15 01:01:55.538543574 +0530 +++ b/lib/utils.h 2019-02-15 01:01:20.114541874 +0530 @@ -70,6 +70,7 @@ extern int inet_sockaddrcmp(struct sockaddr_storage *, struct sockaddr_storage *); extern char *get_local_name(void); extern int string_equal(const char *, const char *); +extern FILE *fopen_safe(const char *, const char *); extern void set_std_fd(int); #if !defined _HAVE_LIBIPTC_ || defined _LIBIPTC_DYNAMIC_ extern int fork_exec(char **argv);