Based on 874bc134ac6504c45e94174e37af13ff21a6bfe2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 14 Jul 2014 16:53:23 -0400
Subject: [PATCH] Clear up confusion wrt. ENTRY_SIZE_MAX and DATA_SIZE_MAX

Define DATA_SIZE_MAX to mean the maximum size of a single
field, and ENTRY_SIZE_MAX to mean the size of the whole
entry, with some rough calculation of overhead over the payload.

Check if entries are not too big when processing native journal
messages.
---
 src/journal/coredump.c        |    6 +++---
 src/journal/journald-native.c |   25 +++++++++++++++++++++----
 2 files changed, 24 insertions(+), 7 deletions(-)
--- src/journal/coredump.c
+++ src/journal/coredump.c	2014-07-16 13:02:54.438235659 +0000
@@ -38,10 +38,10 @@
 #include "cgroup-util.h"
 
 /* Few programs have less than 3MiB resident */
-#define COREDUMP_MIN_START (3*1024*1024)
+#define COREDUMP_MIN_START (3*1024*1024u)
 /* Make sure to not make this larger than the maximum journal entry
- * size. See ENTRY_SIZE_MAX in journald-native.c. */
-#define COREDUMP_MAX (767*1024*1024)
+ * size. See DATA_SIZE_MAX in journald-native.c. */
+#define COREDUMP_MAX (1024*1024*767u)
 
 enum {
         ARG_PID = 1,
--- src/journal/journald-native.c
+++ src/journal/journald-native.c	2014-07-16 12:50:45.000000000 +0000
@@ -34,8 +34,8 @@
 
 /* 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)
+#define ENTRY_SIZE_MAX (1024*1024*770u)
+#define DATA_SIZE_MAX (1024*1024*768u)
 
 static bool valid_user_field(const char *p, size_t l) {
         const char *a;
@@ -86,7 +86,7 @@ void server_process_native_message(
         struct iovec *iovec = NULL;
         unsigned n = 0, j, tn = (unsigned) -1;
         const char *p;
-        size_t remaining, m = 0;
+        size_t remaining, m = 0, entry_size = 0;
         int priority = LOG_INFO;
         char *identifier = NULL, *message = NULL;
         pid_t object_pid = 0;
@@ -110,9 +110,17 @@ void server_process_native_message(
 
                 if (e == p) {
                         /* 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);
+                                continue;
+                        }
+
                         server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
                         n = 0;
                         priority = LOG_INFO;
+                        entry_size = 0;
 
                         p++;
                         remaining--;
@@ -150,6 +158,7 @@ void server_process_native_message(
                                 iovec[n].iov_base = (char*) p;
                                 iovec[n].iov_len = l;
                                 n++;
+                                entry_size += iovec[n].iov_len;
 
                                 /* We need to determine the priority
                                  * of this entry for the rate limiting
@@ -218,7 +227,7 @@ void server_process_native_message(
                         l = le64toh(l_le);
 
                         if (l > DATA_SIZE_MAX) {
-                                log_debug("Received binary data block too large, ignoring.");
+                                log_debug("Received binary data block of %zu bytes is too large, ignoring.", l);
                                 break;
                         }
 
@@ -242,6 +251,7 @@ void server_process_native_message(
                                 iovec[n].iov_base = k;
                                 iovec[n].iov_len = (e - p) + 1 + l;
                                 n++;
+                                entry_size += iovec[n].iov_len;
                         } else
                                 free(k);
 
@@ -255,6 +265,13 @@ void server_process_native_message(
 
         tn = n++;
         IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
+        entry_size += strlen("_TRANSPORT=journal");
+
+        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);
+                goto finish;
+        }
 
         if (message) {
                 if (s->forward_to_syslog)
