diff --git a/keepalived/core/pidfile.c b/keepalived/core/pidfile.c index f3f3a2c8..6cfbfe8d 100644 --- a/keepalived/core/pidfile.c +++ b/keepalived/core/pidfile.c @@ -54,7 +54,7 @@ int 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 --git a/keepalived/vrrp/vrrp_dbus.c b/keepalived/vrrp/vrrp_dbus.c index f29a974f..1320a6c2 100644 --- a/keepalived/vrrp/vrrp_dbus.c +++ b/keepalived/vrrp/vrrp_dbus.c @@ -551,7 +551,7 @@ read_file(gchar* filepath) 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 --git a/keepalived/vrrp/vrrp_print.c b/keepalived/vrrp/vrrp_print.c index 7adb701d..03840adf 100644 --- a/keepalived/vrrp/vrrp_print.c +++ b/keepalived/vrrp/vrrp_print.c @@ -27,6 +27,7 @@ #include "vrrp.h" #include "vrrp_data.h" #include "vrrp_print.h" +#include "utils.h" #ifdef _HAVE_FIB_ROUTING_ #include "vrrp_iproute.h" #include "vrrp_iprule.h" @@ -350,7 +351,7 @@ void 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,7 @@ void vrrp_print_stats(void) { FILE *file; - file = fopen ("/tmp/keepalived.stats","w"); + file = fopen_safe("/tmp/keepalived.stats","w"); if (!file) { log_message(LOG_INFO, "Can't open /tmp/keepalived.stats (%d: %s)", @@ -393,8 +394,7 @@ vrrp_print_stats(void) 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 --git a/lib/memory.c b/lib/memory.c index 96a4e7b9..04b3d6ee 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -441,7 +441,7 @@ mem_log_init(const char* prog_name, const char *banner) } 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 --git a/lib/parser.c b/lib/parser.c index 2f7959e8..a5c3465b 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -153,12 +153,12 @@ dump_keywords(vector_t *keydump, int level, FILE *fp) { 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 --git a/lib/utils.c b/lib/utils.c index 88465609..f317937e 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -89,7 +89,7 @@ dump_buffer(char *buff, size_t count, FILE* fp) 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 @@ string_equal(const char *str1, const char *str2) 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 --git a/lib/utils.h b/lib/utils.h index ec717125..1e440795 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -70,6 +70,7 @@ extern int inet_inaddrcmp(int, void *, void *); 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);