X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Fjournal%2Fjournald-native.c;h=d3735ec73c598706516355aae48239c81afc7bb4;hb=73843b52585d42cc1a970a1c664818ece6942e9e;hp=6bc5df725e504357363fe5a2c21a7b7c39c7289a;hpb=fa1c4b518ec7d8ec2d647213ee651cde4d6c9d7e;p=elogind.git diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index 6bc5df725..d3735ec73 100644 --- a/src/journal/journald-native.c +++ b/src/journal/journald-native.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "socket-util.h" #include "path-util.h" @@ -32,6 +33,7 @@ #include "journald-console.h" #include "journald-syslog.h" #include "journald-wall.h" +#include "memfd.h" bool valid_user_field(const char *p, size_t l, bool allow_protected) { const char *a; @@ -108,8 +110,7 @@ void server_process_native_message( /* Entry separator */ if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */ - log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", - n, entry_size); + log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size); continue; } @@ -134,8 +135,7 @@ void server_process_native_message( /* A property follows */ /* n received properties, +1 for _TRANSPORT */ - if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS + - !!object_pid * N_IOVEC_OBJECT_FIELDS)) { + if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS + !!object_pid * N_IOVEC_OBJECT_FIELDS)) { log_oom(); break; } @@ -153,8 +153,8 @@ void server_process_native_message( * field */ iovec[n].iov_base = (char*) p; iovec[n].iov_len = l; - n++; entry_size += iovec[n].iov_len; + n++; /* We need to determine the priority * of this entry for the rate limiting @@ -246,8 +246,8 @@ void server_process_native_message( if (valid_user_field(p, e - p, false)) { iovec[n].iov_base = k; iovec[n].iov_len = (e - p) + 1 + l; - n++; entry_size += iovec[n].iov_len; + n++; } else free(k); @@ -308,17 +308,27 @@ void server_process_native_file( const char *label, size_t label_len) { struct stat st; - _cleanup_free_ void *p = NULL; - ssize_t n; + bool sealed; int r; + /* Data is in the passed fd, since it didn't fit in a + * datagram. */ + assert(s); assert(fd >= 0); - if (!ucred || ucred->uid != 0) { + /* If it's a memfd, check if it is sealed. If so, we can just + * use map it and use it, and do not need to copy the data + * out. */ + sealed = memfd_get_sealed(fd) > 0; + + if (!sealed && (!ucred || ucred->uid != 0)) { _cleanup_free_ char *sl = NULL, *k = NULL; const char *e; + /* If this is not a sealed memfd, and the peer is unknown or + * unprivileged, then verify the path. */ + if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) { log_oom(); return; @@ -346,11 +356,6 @@ void server_process_native_file( } } - /* 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 - * stupidly read it */ - if (fstat(fd, &st) < 0) { log_error("Failed to stat passed file, ignoring: %m"); return; @@ -369,17 +374,41 @@ void server_process_native_file( return; } - p = malloc(st.st_size); - if (!p) { - log_oom(); - return; - } + if (sealed) { + void *p; + size_t ps; + + /* The file is sealed, we can just map it and use it. */ - n = pread(fd, p, st.st_size, 0); - if (n < 0) - 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); + ps = PAGE_ALIGN(st.st_size); + p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0); + if (p == MAP_FAILED) { + log_error("Failed to map memfd, ignoring: %m"); + return; + } + + server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len); + assert_se(munmap(p, ps) >= 0); + } else { + _cleanup_free_ void *p = NULL; + ssize_t n; + + /* The file is not sealed, we can't map the file here, since + * clients might then truncate it and trigger a SIGBUS for + * us. So let's stupidly read it */ + + p = malloc(st.st_size); + if (!p) { + log_oom(); + return; + } + + n = pread(fd, p, st.st_size, 0); + if (n < 0) + 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); + } } int server_open_native_socket(Server*s) { @@ -419,7 +448,7 @@ int server_open_native_socket(Server*s) { } #ifdef HAVE_SELINUX - if (use_selinux()) { + if (mac_selinux_use()) { one = 1; r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); if (r < 0)