X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournald-native.c;h=3c60b22eaf5550af35c2de30fb7afb4fa5f48077;hp=ac2d0ba148c10c8ddf3c25e1889fc028af54d62a;hb=ed6d629a3487105e31415db9e175dd698ac20125;hpb=8c0b803b97bb0ee6603d9be85fb6b69cd6081eaf diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c index ac2d0ba14..3c60b22ea 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-util.h" bool valid_user_field(const char *p, size_t l, bool allow_protected) { const char *a; @@ -68,15 +70,15 @@ bool valid_user_field(const char *p, size_t l, bool allow_protected) { return true; } -static bool allow_object_pid(struct ucred *ucred) { +static bool allow_object_pid(const struct ucred *ucred) { return ucred && ucred->uid == 0; } void server_process_native_message( Server *s, const void *buffer, size_t buffer_size, - struct ucred *ucred, - struct timeval *tv, + const struct ucred *ucred, + const struct timeval *tv, const char *label, size_t label_len) { struct iovec *iovec = NULL; @@ -301,22 +303,32 @@ finish: void server_process_native_file( Server *s, int fd, - struct ucred *ucred, - struct timeval *tv, + const struct ucred *ucred, + const struct timeval *tv, 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,21 +374,46 @@ 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. */ + + 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 */ - 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); + 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) { - int one, r; + static const int one = 1; + int r; assert(s); @@ -409,7 +441,6 @@ int server_open_native_socket(Server*s) { } else fd_nonblock(s->native_fd, 1); - one = 1; r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); if (r < 0) { log_error("SO_PASSCRED failed: %m"); @@ -417,15 +448,13 @@ int server_open_native_socket(Server*s) { } #ifdef HAVE_SELINUX - if (use_selinux()) { - one = 1; + if (mac_selinux_use()) { r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one)); if (r < 0) log_warning("SO_PASSSEC failed: %m"); } #endif - one = 1; r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one)); if (r < 0) { log_error("SO_TIMESTAMP failed: %m");