|
|
a3e2b5 |
From ed028441cc2ef0ffb9771d7266d40f18910f0ae1 Mon Sep 17 00:00:00 2001
|
|
|
a3e2b5 |
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
|
|
a3e2b5 |
Date: Wed, 5 Dec 2018 22:50:39 +0100
|
|
|
a3e2b5 |
Subject: [PATCH] journald: when processing a native message, bail more quickly
|
|
|
a3e2b5 |
on overbig messages
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
We'd first parse all or most of the message, and only then consider if it
|
|
|
a3e2b5 |
is not too large. Also, when encountering a single field over the limit,
|
|
|
a3e2b5 |
we'd still process the preceding part of the message. Let's be stricter,
|
|
|
a3e2b5 |
and check size limits early, and let's refuse the whole message if it fails
|
|
|
a3e2b5 |
any of the size limits.
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
(cherry-picked from commit 964ef920ea6735d39f856b05fd8ef451a09a6a1d)
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
Related: #1664977
|
|
|
a3e2b5 |
---
|
|
|
a3e2b5 |
src/journal/journald-native.c | 65 ++++++++++++++++++++---------------
|
|
|
a3e2b5 |
1 file changed, 37 insertions(+), 28 deletions(-)
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
|
|
|
a3e2b5 |
index 951d092053..110ab3641c 100644
|
|
|
a3e2b5 |
--- a/src/journal/journald-native.c
|
|
|
a3e2b5 |
+++ b/src/journal/journald-native.c
|
|
|
a3e2b5 |
@@ -109,7 +109,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
int priority = LOG_INFO;
|
|
|
a3e2b5 |
pid_t object_pid = 0;
|
|
|
a3e2b5 |
const char *p;
|
|
|
a3e2b5 |
- int r = 0;
|
|
|
a3e2b5 |
+ int r = 1;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
p = buffer;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -121,8 +121,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
if (!e) {
|
|
|
a3e2b5 |
/* Trailing noise, let's ignore it, and flush what we collected */
|
|
|
a3e2b5 |
log_debug("Received message with trailing noise, ignoring.");
|
|
|
a3e2b5 |
- r = 1; /* finish processing of the message */
|
|
|
a3e2b5 |
- break;
|
|
|
a3e2b5 |
+ break; /* finish processing of the message */
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (e == p) {
|
|
|
a3e2b5 |
@@ -132,8 +131,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (IN_SET(*p, '.', '#')) {
|
|
|
a3e2b5 |
- /* Ignore control commands for now, and
|
|
|
a3e2b5 |
- * comments too. */
|
|
|
a3e2b5 |
+ /* Ignore control commands for now, and comments too. */
|
|
|
a3e2b5 |
*remaining -= (e - p) + 1;
|
|
|
a3e2b5 |
p = e + 1;
|
|
|
a3e2b5 |
continue;
|
|
|
a3e2b5 |
@@ -142,7 +140,6 @@ static int server_process_entry(
|
|
|
a3e2b5 |
/* A property follows */
|
|
|
a3e2b5 |
if (n > ENTRY_FIELD_COUNT_MAX) {
|
|
|
a3e2b5 |
log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry.");
|
|
|
a3e2b5 |
- r = 1;
|
|
|
a3e2b5 |
goto finish;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -152,7 +149,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS +
|
|
|
a3e2b5 |
client_context_extra_fields_n_iovec(context))) {
|
|
|
a3e2b5 |
r = log_oom();
|
|
|
a3e2b5 |
- break;
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
q = memchr(p, '=', e - p);
|
|
|
a3e2b5 |
@@ -161,6 +158,16 @@ static int server_process_entry(
|
|
|
a3e2b5 |
size_t l;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
l = e - p;
|
|
|
a3e2b5 |
+ if (l > DATA_SIZE_MAX) {
|
|
|
a3e2b5 |
+ log_debug("Received text block of %zu bytes is too large, ignoring entry.", l);
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
+ }
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
+ if (entry_size + l + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
|
|
|
a3e2b5 |
+ log_debug("Entry is too big (%zu bytes after processing %zu entries), ignoring entry.",
|
|
|
a3e2b5 |
+ entry_size + l, n + 1);
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
+ }
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* If the field name starts with an underscore, skip the variable, since that indicates
|
|
|
a3e2b5 |
* a trusted field */
|
|
|
a3e2b5 |
@@ -178,7 +185,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
p = e + 1;
|
|
|
a3e2b5 |
continue;
|
|
|
a3e2b5 |
} else {
|
|
|
a3e2b5 |
- uint64_t l;
|
|
|
a3e2b5 |
+ uint64_t l, total;
|
|
|
a3e2b5 |
char *k;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (*remaining < e - p + 1 + sizeof(uint64_t) + 1) {
|
|
|
a3e2b5 |
@@ -187,10 +194,16 @@ static int server_process_entry(
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
l = unaligned_read_le64(e + 1);
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
if (l > DATA_SIZE_MAX) {
|
|
|
a3e2b5 |
- log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l);
|
|
|
a3e2b5 |
- break;
|
|
|
a3e2b5 |
+ log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring entry.", l);
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
+ }
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
+ total = (e - p) + 1 + l;
|
|
|
a3e2b5 |
+ if (entry_size + total + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
|
|
|
a3e2b5 |
+ log_debug("Entry is too big (%"PRIu64"bytes after processing %zu fields), ignoring.",
|
|
|
a3e2b5 |
+ entry_size + total, n + 1);
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if ((uint64_t) *remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
|
|
|
a3e2b5 |
@@ -199,7 +212,7 @@ static int server_process_entry(
|
|
|
a3e2b5 |
break;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- k = malloc((e - p) + 1 + l);
|
|
|
a3e2b5 |
+ k = malloc(total);
|
|
|
a3e2b5 |
if (!k) {
|
|
|
a3e2b5 |
log_oom();
|
|
|
a3e2b5 |
break;
|
|
|
a3e2b5 |
@@ -228,15 +241,8 @@ static int server_process_entry(
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (n <= 0) {
|
|
|
a3e2b5 |
- r = 1;
|
|
|
a3e2b5 |
+ if (n <= 0)
|
|
|
a3e2b5 |
goto finish;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- if (!client_context_test_priority(context, priority)) {
|
|
|
a3e2b5 |
- r = 0;
|
|
|
a3e2b5 |
- goto finish;
|
|
|
a3e2b5 |
- }
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
tn = n++;
|
|
|
a3e2b5 |
iovec[tn] = IOVEC_MAKE_STRING("_TRANSPORT=journal");
|
|
|
a3e2b5 |
@@ -247,6 +253,11 @@ static int server_process_entry(
|
|
|
a3e2b5 |
goto finish;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
+ r = 0; /* Success, we read the message. */
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
+ if (!client_context_test_priority(context, priority))
|
|
|
a3e2b5 |
+ goto finish;
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
if (message) {
|
|
|
a3e2b5 |
if (s->forward_to_syslog)
|
|
|
a3e2b5 |
server_forward_syslog(s, syslog_fixup_facility(priority), identifier, message, ucred, tv);
|
|
|
a3e2b5 |
@@ -318,15 +329,13 @@ void server_process_native_file(
|
|
|
a3e2b5 |
bool sealed;
|
|
|
a3e2b5 |
int r;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- /* Data is in the passed fd, since it didn't fit in a
|
|
|
a3e2b5 |
- * datagram. */
|
|
|
a3e2b5 |
+ /* Data is in the passed fd, probably it didn't fit in a datagram. */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
assert(s);
|
|
|
a3e2b5 |
assert(fd >= 0);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* If it's a memfd, check if it is sealed. If so, we can just
|
|
|
a3e2b5 |
- * use map it and use it, and do not need to copy the data
|
|
|
a3e2b5 |
- * out. */
|
|
|
a3e2b5 |
+ * mmap it and use it, and do not need to copy the data out. */
|
|
|
a3e2b5 |
sealed = memfd_get_sealed(fd) > 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (!sealed && (!ucred || ucred->uid != 0)) {
|
|
|
a3e2b5 |
@@ -397,7 +406,7 @@ void server_process_native_file(
|
|
|
a3e2b5 |
ssize_t n;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (fstatvfs(fd, &vfs) < 0) {
|
|
|
a3e2b5 |
- log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
|
|
|
a3e2b5 |
+ log_error_errno(errno, "Failed to stat file system of passed file, not processing it: %m");
|
|
|
a3e2b5 |
return;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -407,7 +416,7 @@ void server_process_native_file(
|
|
|
a3e2b5 |
* https://github.com/systemd/systemd/issues/1822
|
|
|
a3e2b5 |
*/
|
|
|
a3e2b5 |
if (vfs.f_flag & ST_MANDLOCK) {
|
|
|
a3e2b5 |
- log_error("Received file descriptor from file system with mandatory locking enabled, refusing.");
|
|
|
a3e2b5 |
+ log_error("Received file descriptor from file system with mandatory locking enabled, not processing it.");
|
|
|
a3e2b5 |
return;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -420,13 +429,13 @@ void server_process_native_file(
|
|
|
a3e2b5 |
* and so is SMB. */
|
|
|
a3e2b5 |
r = fd_nonblock(fd, true);
|
|
|
a3e2b5 |
if (r < 0) {
|
|
|
a3e2b5 |
- log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
|
|
|
a3e2b5 |
+ log_error_errno(r, "Failed to make fd non-blocking, not processing it: %m");
|
|
|
a3e2b5 |
return;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* The file is not sealed, we can't map the file here, since
|
|
|
a3e2b5 |
* clients might then truncate it and trigger a SIGBUS for
|
|
|
a3e2b5 |
- * us. So let's stupidly read it */
|
|
|
a3e2b5 |
+ * us. So let's stupidly read it. */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
p = malloc(st.st_size);
|
|
|
a3e2b5 |
if (!p) {
|