X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjournal%2Fjournald-native.c;h=d3735ec73c598706516355aae48239c81afc7bb4;hb=73843b52585d42cc1a970a1c664818ece6942e9e;hp=a6352022dd8b55422b2707fb2b618f1ab26b7cef;hpb=6baa7db00812437bbc87e73faa1a11b6cf631958;p=elogind.git diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index a6352022d..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; @@ -306,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; @@ -344,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; @@ -367,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) {