X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fjournald-native.c;h=ec9afa187de97be3fd9245219843cba637527b24;hb=fd59d9f29838c3888168554c774003e7ad6d33b0;hp=7aa99a399071defba07eff3ca004ae9ad193bfa3;hpb=0153028ae379eb7c9a463c548ef73ea392c6cdb0;p=elogind.git diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 7aa99a399..ec9afa187 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -20,16 +20,21 @@ ***/ #include +#include #include #include "socket-util.h" -#include "journald.h" +#include "path-util.h" +#include "journald-server.h" #include "journald-native.h" #include "journald-kmsg.h" #include "journald-console.h" #include "journald-syslog.h" -#define ENTRY_SIZE_MAX (1024*1024*32) +/* Make sure not to make this smaller than the maximum coredump + * size. See COREDUMP_MAX in coredump.c */ +#define ENTRY_SIZE_MAX (1024*1024*768) +#define DATA_SIZE_MAX (1024*1024*768) static bool valid_user_field(const char *p, size_t l) { const char *a; @@ -118,11 +123,12 @@ void server_process_native_message( /* A property follows */ - if (n+N_IOVEC_META_FIELDS >= m) { + /* n received properties, +1 for _TRANSPORT */ + if (n + 1 + N_IOVEC_META_FIELDS >= m) { struct iovec *c; unsigned u; - u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U); + u = MAX((n + 1 + N_IOVEC_META_FIELDS) * 2U, 4U); c = realloc(iovec, u * sizeof(struct iovec)); if (!c) { log_oom(); @@ -152,23 +158,23 @@ void server_process_native_message( * of this entry for the rate limiting * logic */ if (l == 10 && - memcmp(p, "PRIORITY=", 9) == 0 && + hasprefix(p, "PRIORITY=") && p[9] >= '0' && p[9] <= '9') priority = (priority & LOG_FACMASK) | (p[9] - '0'); else if (l == 17 && - memcmp(p, "SYSLOG_FACILITY=", 16) == 0 && + hasprefix(p, "SYSLOG_FACILITY=") && p[16] >= '0' && p[16] <= '9') priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3); else if (l == 18 && - memcmp(p, "SYSLOG_FACILITY=", 16) == 0 && + hasprefix(p, "SYSLOG_FACILITY=") && p[16] >= '0' && p[16] <= '9' && p[17] >= '0' && p[17] <= '9') priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3); else if (l >= 19 && - memcmp(p, "SYSLOG_IDENTIFIER=", 18) == 0) { + hasprefix(p, "SYSLOG_IDENTIFIER=")) { char *t; t = strndup(p + 18, l - 18); @@ -177,7 +183,7 @@ void server_process_native_message( identifier = t; } } else if (l >= 8 && - memcmp(p, "MESSAGE=", 8) == 0) { + hasprefix(p, "MESSAGE=")) { char *t; t = strndup(p + 8, l - 8); @@ -204,7 +210,12 @@ void server_process_native_message( memcpy(&l_le, e + 1, sizeof(uint64_t)); l = le64toh(l_le); - if (remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || + if (l > DATA_SIZE_MAX) { + log_debug("Received binary data block too large, ignoring."); + break; + } + + if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 || e[1+sizeof(uint64_t)+l] != '\n') { log_debug("Failed to parse message, ignoring."); break; @@ -274,12 +285,44 @@ void server_process_native_file( const char *label, size_t label_len) { struct stat st; - void *p; + _cleanup_free_ void *p = NULL; ssize_t n; + int r; assert(s); assert(fd >= 0); + if (!ucred || ucred->uid != 0) { + _cleanup_free_ char *sl = NULL, *k = NULL; + const char *e; + + if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) { + log_oom(); + return; + } + + r = readlink_malloc(sl, &k); + if (r < 0) { + log_error("readlink(%s) failed: %m", sl); + return; + } + + e = path_startswith(k, "/dev/shm/"); + if (!e) + e = path_startswith(k, "/tmp/"); + if (!e) + e = path_startswith(k, "/var/tmp/"); + if (!e) { + log_error("Received file outside of allowed directories. Refusing."); + return; + } + + if (!filename_is_safe(e)) { + log_error("Received file in subdirectory of allowed directories. Refusing."); + return; + } + } + /* Data is in the passed file, since it didn't fit in a * datagram. We can't map the file here, since clients might * then truncate it and trigger a SIGBUS for us. So let's @@ -314,8 +357,6 @@ void server_process_native_file( log_error("Failed to read file, ignoring: %s", strerror(-n)); else if (n > 0) server_process_native_message(s, p, n, ucred, tv, label, label_len); - - free(p); } int server_open_native_socket(Server*s) { @@ -358,7 +399,7 @@ int server_open_native_socket(Server*s) { #ifdef HAVE_SELINUX one = 1; - r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); + r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); if (r < 0) log_warning("SO_PASSSEC failed: %m"); #endif