blob: ae9ef5de56fa47c225b0af99f7f7ea463c6e708c [file] [log] [blame]
Brad Bishopf8caae32019-03-25 13:13:56 -04001From 7cad044b72406cbadf048da432c29afea74c3c10 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Wed, 5 Dec 2018 22:45:02 +0100
4Subject: [PATCH] journald: set a limit on the number of fields
5
6The fix for CVE-2018-16865 is plucked from two commits that have
7been pushed to systemd master.
8
9journald: set a limit on the number of fields (1k)
10
11We allocate a iovec entry for each field, so with many short entries,
12our memory usage and processing time can be large, even with a relatively
13small message size. Let's refuse overly long entries.
14
15CVE-2018-16865
16https://bugzilla.redhat.com/show_bug.cgi?id=1653861
17
18What from I can see, the problem is not from an alloca, despite what the CVE
19description says, but from the attack multiplication that comes from creating
20many very small iovecs: (void* + size_t) for each three bytes of input message.
21
22Patch backported from systemd master at
23052c57f132f04a3cf4148f87561618da1a6908b4.
24
25journal-remote: set a limit on the number of fields in a message
26
27Existing use of E2BIG is replaced with ENOBUFS (entry too long), and E2BIG is
28reused for the new error condition (too many fields).
29
30This matches the change done for systemd-journald, hence forming the second
31part of the fix for CVE-2018-16865
32(https://bugzilla.redhat.com/show_bug.cgi?id=1653861).
33
34Patch backported from systemd master at
35ef4d6abe7c7fab6cbff975b32e76b09feee56074.
36with the changes applied by 7fdb237f5473cb8fc2129e57e8a0039526dcb4fd
37removed.
38
39CVE: CVE-2018-16865
40Upstream-Status: Backport
41Signed-off-by: Marcus Cooper <marcusc@axis.com>
42---
43 src/basic/journal-importer.c | 5 ++++-
44 src/basic/journal-importer.h | 3 +++
45 src/journal-remote/journal-remote-main.c | 7 ++++++-
46 src/journal-remote/journal-remote.c | 5 ++++-
47 src/journal/journald-native.c | 5 +++++
48 5 files changed, 22 insertions(+), 3 deletions(-)
49
50diff --git a/src/basic/journal-importer.c b/src/basic/journal-importer.c
51index ca203bbbfc..3ac55a66d9 100644
52--- a/src/basic/journal-importer.c
53+++ b/src/basic/journal-importer.c
54@@ -23,6 +23,9 @@ enum {
55 };
56
57 static int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) {
58+ if (iovw->count >= ENTRY_FIELD_COUNT_MAX)
59+ return -E2BIG;
60+
61 if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
62 return log_oom();
63
64@@ -98,7 +101,7 @@ static int get_line(JournalImporter *imp, char **line, size_t *size) {
65 imp->scanned = imp->filled;
66 if (imp->scanned >= DATA_SIZE_MAX) {
67 log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
68- return -E2BIG;
69+ return -ENOBUFS;
70 }
71
72 if (imp->passive_fd)
73diff --git a/src/basic/journal-importer.h b/src/basic/journal-importer.h
74index f49ce734a1..c4ae45d32d 100644
75--- a/src/basic/journal-importer.h
76+++ b/src/basic/journal-importer.h
77@@ -16,6 +16,9 @@
78 #define DATA_SIZE_MAX (1024*1024*768u)
79 #define LINE_CHUNK 8*1024u
80
81+/* The maximum number of fields in an entry */
82+#define ENTRY_FIELD_COUNT_MAX 1024
83+
84 struct iovec_wrapper {
85 struct iovec *iovec;
86 size_t size_bytes;
87diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
88index 8fda9d1499..3a01fef646 100644
89--- a/src/journal-remote/journal-remote-main.c
90+++ b/src/journal-remote/journal-remote-main.c
91@@ -212,7 +212,12 @@ static int process_http_upload(
92 break;
93 else if (r < 0) {
94 log_warning("Failed to process data for connection %p", connection);
95- if (r == -E2BIG)
96+ if (r == -ENOBUFS)
97+ return mhd_respondf(connection,
98+ r, MHD_HTTP_PAYLOAD_TOO_LARGE,
99+ "Entry is above the maximum of %u, aborting connection %p.",
100+ DATA_SIZE_MAX, connection);
101+ else if (r == -E2BIG)
102 return mhd_respondf(connection,
103 r, MHD_HTTP_PAYLOAD_TOO_LARGE,
104 "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
105diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
106index beb75a1cb4..67e3a70c06 100644
107--- a/src/journal-remote/journal-remote.c
108+++ b/src/journal-remote/journal-remote.c
109@@ -408,7 +408,10 @@ int journal_remote_handle_raw_source(
110 log_debug("%zu active sources remaining", s->active);
111 return 0;
112 } else if (r == -E2BIG) {
113- log_notice_errno(E2BIG, "Entry too big, skipped");
114+ log_notice("Entry with too many fields, skipped");
115+ return 1;
116+ } else if (r == -ENOBUFS) {
117+ log_notice("Entry too big, skipped");
118 return 1;
119 } else if (r == -EAGAIN) {
120 return 0;
121diff --git a/src/journal/journald-native.c b/src/journal/journald-native.c
122index 5ff22a10af..951d092053 100644
123--- a/src/journal/journald-native.c
124+++ b/src/journal/journald-native.c
125@@ -140,6 +140,11 @@ static int server_process_entry(
126 }
127
128 /* A property follows */
129+ if (n > ENTRY_FIELD_COUNT_MAX) {
130+ log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry.");
131+ r = 1;
132+ goto finish;
133+ }
134
135 /* n existing properties, 1 new, +1 for _TRANSPORT */
136 if (!GREEDY_REALLOC(iovec, m,
137--
1382.11.0
139