Browse code

Fix systemd CVE-2018-16864, CVE-2018-16865, CVE-2018-16866

Change-Id: I35fc9dff46de1af1f9d14bb49f8454810d6594ab
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6593
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Anish Swaminathan <anishs@vmware.com>

suezzelur authored on 2019/01/25 17:01:24
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,204 @@
0
+diff -rup systemd-233/src/basic/io-util.c systemd-233-new/src/basic/io-util.c
1
+--- systemd-233/src/basic/io-util.c	2017-03-01 13:43:06.000000000 -0800
2
+@@ -25,6 +25,7 @@
3
+ #include <unistd.h>
4
+ 
5
+ #include "io-util.h"
6
++#include "string-util.h"
7
+ #include "time-util.h"
8
+ 
9
+ int flush_fd(int fd) {
10
+@@ -267,3 +268,20 @@ ssize_t sparse_write(int fd, const void
11
+ 
12
+         return q - (const uint8_t*) p;
13
+ }
14
++
15
++char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
16
++        char *x;
17
++
18
++        x = strappend(field, value);
19
++        if (x)
20
++                iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
21
++        return x;
22
++}
23
++
24
++char* set_iovec_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
25
++        char *x;
26
++
27
++        x = set_iovec_string_field(iovec, n_iovec, field, value);
28
++        free(value);
29
++        return x;
30
++}
31
+diff -rup systemd-233/src/basic/io-util.h systemd-233-new/src/basic/io-util.h
32
+--- systemd-233/src/basic/io-util.h	2017-03-01 13:43:06.000000000 -0800
33
+@@ -93,3 +93,10 @@ static inline bool FILE_SIZE_VALID_OR_IN
34
+         return FILE_SIZE_VALID(l);
35
+ 
36
+ }
37
++
38
++#define IOVEC_INIT(base, len) { .iov_base = (base), .iov_len = (len) }
39
++#define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len)
40
++#define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string))
41
++#define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string)
42
++char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value);
43
++char* set_iovec_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value);
44
+diff -rup systemd-233/src/coredump/coredump.c systemd-233-new/src/coredump/coredump.c
45
+--- systemd-233/src/coredump/coredump.c	2017-03-01 13:43:06.000000000 -0800
46
+@@ -1066,23 +1066,6 @@ static int send_iovec(const struct iovec
47
+         return 0;
48
+ }
49
+ 
50
+-static char* set_iovec_field(struct iovec iovec[27], size_t *n_iovec, const char *field, const char *value) {
51
+-        char *x;
52
+-
53
+-        x = strappend(field, value);
54
+-        if (x)
55
+-                IOVEC_SET_STRING(iovec[(*n_iovec)++], x);
56
+-        return x;
57
+-}
58
+-
59
+-static char* set_iovec_field_free(struct iovec iovec[27], size_t *n_iovec, const char *field, char *value) {
60
+-        char *x;
61
+-
62
+-        x = set_iovec_field(iovec, n_iovec, field, value);
63
+-        free(value);
64
+-        return x;
65
+-}
66
+-
67
+ static int gather_pid_metadata(
68
+                 char* context[_CONTEXT_MAX],
69
+                 char **comm_fallback,
70
+@@ -1128,33 +1111,33 @@ static int gather_pid_metadata(
71
+                         (void) write_string_file("/proc/sys/kernel/core_pattern", "|/bin/false", 0);
72
+                 }
73
+ 
74
+-                set_iovec_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
75
++                set_iovec_string_field(iovec, n_iovec, "COREDUMP_UNIT=", context[CONTEXT_UNIT]);
76
+         }
77
+ 
78
+         if (cg_pid_get_user_unit(pid, &t) >= 0)
79
+                 set_iovec_field_free(iovec, n_iovec, "COREDUMP_USER_UNIT=", t);
80
+ 
81
+         /* The next few are mandatory */
82
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
83
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_PID=", context[CONTEXT_PID]))
84
+                 return log_oom();
85
+ 
86
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
87
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_UID=", context[CONTEXT_UID]))
88
+                 return log_oom();
89
+ 
90
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
91
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_GID=", context[CONTEXT_GID]))
92
+                 return log_oom();
93
+ 
94
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
95
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL=", context[CONTEXT_SIGNAL]))
96
+                 return log_oom();
97
+ 
98
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
99
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_RLIMIT=", context[CONTEXT_RLIMIT]))
100
+                 return log_oom();
101
+ 
102
+-        if (!set_iovec_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
103
++        if (!set_iovec_string_field(iovec, n_iovec, "COREDUMP_COMM=", context[CONTEXT_COMM]))
104
+                 return log_oom();
105
+ 
106
+         if (context[CONTEXT_EXE] &&
107
+-            !set_iovec_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
108
++            !set_iovec_string_field(iovec, n_iovec, "COREDUMP_EXE=", context[CONTEXT_EXE]))
109
+                 return log_oom();
110
+ 
111
+         if (sd_pid_get_session(pid, &t) >= 0)
112
+@@ -1222,7 +1205,7 @@ static int gather_pid_metadata(
113
+                 IOVEC_SET_STRING(iovec[(*n_iovec)++], t);
114
+ 
115
+         if (safe_atoi(context[CONTEXT_SIGNAL], &signo) >= 0 && SIGNAL_VALID(signo))
116
+-                set_iovec_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
117
++                set_iovec_string_field(iovec, n_iovec, "COREDUMP_SIGNAL_NAME=SIG", signal_to_string(signo));
118
+ 
119
+         return 0; /* we successfully acquired all metadata */
120
+ }
121
+diff -rup systemd-233/src/journal/journald-server.c systemd-233-new/src/journal/journald-server.c
122
+--- systemd-233/src/journal/journald-server.c	2017-03-01 13:43:06.000000000 -0800
123
+@@ -754,7 +754,7 @@ static int get_invocation_id(const char
124
+ 
125
+ static void dispatch_message_real(
126
+                 Server *s,
127
+-                struct iovec *iovec, unsigned n, unsigned m,
128
++                struct iovec *iovec, size_t n, size_t m,
129
+                 const struct ucred *ucred,
130
+                 const struct timeval *tv,
131
+                 const char *label, size_t label_len,
132
+@@ -771,6 +771,7 @@ static void dispatch_message_real(
133
+                 o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)],
134
+                 o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)],
135
+                 o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)];
136
++        _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL;
137
+         uid_t object_uid;
138
+         gid_t object_gid;
139
+         char *x;
140
+@@ -821,9 +822,9 @@ static void dispatch_message_real(
141
+ 
142
+                 r = get_process_cmdline(ucred->pid, 0, false, &t);
143
+                 if (r >= 0) {
144
+-                        x = strjoina("_CMDLINE=", t);
145
+-                        free(t);
146
+-                        IOVEC_SET_STRING(iovec[n++], x);
147
++                        /* At most _SC_ARG_MAX (2MB usually), which is too much to put on stack.
148
++                         * Let's use a heap allocation for this one. */
149
++                        cmdline1 = set_iovec_field_free(iovec, &n, "_CMDLINE=", t);
150
+                 }
151
+ 
152
+                 r = get_process_capeff(ucred->pid, &t);
153
+@@ -968,9 +969,7 @@ static void dispatch_message_real(
154
+ 
155
+                 r = get_process_cmdline(object_pid, 0, false, &t);
156
+                 if (r >= 0) {
157
+-                        x = strjoina("OBJECT_CMDLINE=", t);
158
+-                        free(t);
159
+-                        IOVEC_SET_STRING(iovec[n++], x);
160
++                        cmdline2 = set_iovec_field_free(iovec, &n, "OBJECT_CMDLINE=", t);
161
+                 }
162
+ 
163
+ #ifdef HAVE_AUDIT
164
+@@ -1070,7 +1069,7 @@ static void dispatch_message_real(
165
+ 
166
+ void server_driver_message(Server *s, const char *message_id, const char *format, ...) {
167
+         struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS];
168
+-        unsigned n = 0, m;
169
++        unsigned int n = 0, m;
170
+         int r;
171
+         va_list ap;
172
+         struct ucred ucred = {};
173
+@@ -1100,7 +1099,7 @@ void server_driver_message(Server *s, co
174
+         ucred.gid = getgid();
175
+ 
176
+         if (r >= 0)
177
+-                dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
178
++                dispatch_message_real(s, iovec, (size_t)n, (size_t)ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
179
+ 
180
+         while (m < n)
181
+                 free(iovec[m++].iov_base);
182
+@@ -1114,7 +1113,7 @@ void server_driver_message(Server *s, co
183
+                 n = 3;
184
+                 IOVEC_SET_STRING(iovec[n++], "PRIORITY=4");
185
+                 IOVEC_SET_STRING(iovec[n++], buf);
186
+-                dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
187
++                dispatch_message_real(s, iovec, (size_t)n, (size_t)ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0, NULL);
188
+         }
189
+ }
190
+ 
191
+@@ -1185,7 +1184,7 @@ finish:
192
+         /* restore cgroup path for logging */
193
+         if (c)
194
+                 *c = '/';
195
+-        dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid, path);
196
++        dispatch_message_real(s, iovec, (size_t)n, (size_t)m, ucred, tv, label, label_len, unit_id, priority, object_pid, path);
197
+ }
198
+ 
199
+ int server_flush_to_var(Server *s, bool require_flag_file) {
0 200
new file mode 100644
... ...
@@ -0,0 +1,101 @@
0
+Subject: [PATCH 06/11] journald: set a limit on the number of fields (1k)
1
+
2
+We allocate a iovec entry for each field, so with many short entries,
3
+our memory usage and processing time can be large, even with a relatively
4
+small message size. Let's refuse overly long entries.
5
+
6
+CVE-2018-16865
7
+https://bugzilla.redhat.com/show_bug.cgi?id=1653861
8
+
9
+What from I can see, the problem is not from an alloca, despite what the CVE
10
+description says, but from the attack multiplication that comes from creating
11
+many very small iovecs: (void* + size_t) for each three bytes of input message.
12
+
13
+Subject: [PATCH 11/11] journal-remote: set a limit on the number of fields in
14
+ a message
15
+
16
+Existing use of E2BIG is replaced with ENOBUFS (entry too long), and E2BIG is
17
+reused for the new error condition (too many fields).
18
+
19
+This matches the change done for systemd-journald, hence forming the second
20
+part of the fix for CVE-2018-16865
21
+(https://bugzilla.redhat.com/show_bug.cgi?id=1653861).
22
+
23
+diff -rup systemd-233/src/basic/journal-importer.c systemd-233-new/src/basic/journal-importer.c
24
+--- systemd-233/src/basic/journal-importer.c	2017-03-01 13:43:06.000000000 -0800
25
+@@ -34,6 +34,9 @@ enum {
26
+ };
27
+ 
28
+ static int iovw_put(struct iovec_wrapper *iovw, void* data, size_t len) {
29
++        if (iovw->count >= ENTRY_FIELD_COUNT_MAX)
30
++                return -E2BIG;
31
++
32
+         if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
33
+                 return log_oom();
34
+ 
35
+@@ -108,7 +111,7 @@ static int get_line(JournalImporter *imp
36
+                 imp->scanned = imp->filled;
37
+                 if (imp->scanned >= DATA_SIZE_MAX) {
38
+                         log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
39
+-                        return -E2BIG;
40
++                        return -ENOBUFS;
41
+                 }
42
+ 
43
+                 if (imp->passive_fd)
44
+diff -rup systemd-233/src/basic/journal-importer.h systemd-233-new/src/basic/journal-importer.h
45
+--- systemd-233/src/basic/journal-importer.h	2017-03-01 13:43:06.000000000 -0800
46
+@@ -31,6 +31,9 @@
47
+ #define DATA_SIZE_MAX (1024*1024*768u)
48
+ #define LINE_CHUNK 8*1024u
49
+ 
50
++/* The maximum number of fields in an entry */
51
++#define ENTRY_FIELD_COUNT_MAX 1024
52
++
53
+ struct iovec_wrapper {
54
+         struct iovec *iovec;
55
+         size_t size_bytes;
56
+diff -rup systemd-233/src/journal/journald-native.c systemd-233-new/src/journal/journald-native.c
57
+--- systemd-233/src/journal/journald-native.c	2017-03-01 13:43:06.000000000 -0800
58
+@@ -139,6 +139,10 @@ void server_process_native_message(
59
+                 }
60
+ 
61
+                 /* A property follows */
62
++                if (n > ENTRY_FIELD_COUNT_MAX) {
63
++                        log_debug("Received an entry that has more than " STRINGIFY(ENTRY_FIELD_COUNT_MAX) " fields, ignoring entry.");
64
++                        goto finish;
65
++                }
66
+ 
67
+                 /* n existing properties, 1 new, +1 for _TRANSPORT */
68
+                 if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) {
69
+diff -rup systemd-233/src/journal-remote/journal-remote.c systemd-233-new/src/journal-remote/journal-remote.c
70
+--- systemd-233/src/journal-remote/journal-remote.c	2017-03-01 13:43:06.000000000 -0800
71
+@@ -527,10 +527,14 @@ static int process_http_upload(
72
+                         break;
73
+                 else if (r < 0) {
74
+                         log_warning("Failed to process data for connection %p", connection);
75
+-                        if (r == -E2BIG)
76
++                        if (r == -ENOBUFS)
77
+                                 return mhd_respondf(connection,
78
+                                                     r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
79
+                                                     "Entry is too large, maximum is " STRINGIFY(DATA_SIZE_MAX) " bytes.");
80
++                        else if (r == -E2BIG)
81
++                                return mhd_respondf(connection,
82
++                                                    r, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE,
83
++                                                    "Entry with more fields than the maximum of " STRINGIFY(ENTRY_FIELD_COUNT_MAX) ".");
84
+                         else
85
+                                 return mhd_respondf(connection,
86
+                                                     r, MHD_HTTP_UNPROCESSABLE_ENTITY,
87
+@@ -1053,6 +1057,9 @@ static int handle_raw_source(sd_event_so
88
+                 log_debug("%zu active sources remaining", s->active);
89
+                 return 0;
90
+         } else if (r == -E2BIG) {
91
++                log_notice("Entry with too many fields, skipped");
92
++                return 1;
93
++        } else if (r == -ENOBUFS) {
94
+                 log_notice_errno(E2BIG, "Entry too big, skipped");
95
+                 return 1;
96
+         } else if (r == -EAGAIN) {
0 97
new file mode 100644
... ...
@@ -0,0 +1,60 @@
0
+From a6aadf4ae0bae185dc4c414d492a4a781c80ffe5 Mon Sep 17 00:00:00 2001
1
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
2
+Date: Wed, 8 Aug 2018 15:06:36 +0900
3
+Subject: [PATCH] journal: fix syslog_parse_identifier()
4
+
5
+Fixes #9829.
6
+---
7
+ src/journal/journald-syslog.c     |  6 +++---
8
+ src/journal/test-journal-syslog.c | 10 ++++++++--
9
+ 2 files changed, 11 insertions(+), 5 deletions(-)
10
+
11
+--- a/src/journal/journald-syslog.c
12
+@@ -212,7 +212,7 @@
13
+         e = l;
14
+         l--;
15
+ 
16
+-        if (p[l-1] == ']') {
17
++        if (l > 0 && p[l-1] == ']') {
18
+                 size_t k = l-1;
19
+ 
20
+                 for (;;) {
21
+@@ -237,8 +237,8 @@
22
+         if (t)
23
+                 *identifier = t;
24
+ 
25
+-        if (strchr(WHITESPACE, p[e]))
26
+-                e++;
27
++        e += strspn(p + e, WHITESPACE);
28
++
29
+         *buf = p + e;
30
+         return e;
31
+ }
32
+--- a/src/journal/test-journal-syslog.c
33
+@@ -23,8 +23,8 @@
34
+ #include "macro.h"
35
+ #include "string-util.h"
36
+ 
37
+-static void test_syslog_parse_identifier(const char* str,
38
+-                                         const char *ident, const char*pid, int ret) {
39
++static void test_syslog_parse_identifier(const char *str,
40
++                                         const char *ident, const char *pid, int ret) {
41
+         const char *buf = str;
42
+         _cleanup_free_ char *ident2 = NULL, *pid2 = NULL;
43
+         int ret2;
44
+@@ -39,7 +39,13 @@
45
+ int main(void) {
46
+         test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", 11);
47
+         test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, 6);
48
++        test_syslog_parse_identifier("pidu:  xxx", "pidu", NULL, 7);
49
+         test_syslog_parse_identifier("pidu xxx", NULL, NULL, 0);
50
++        test_syslog_parse_identifier(":", "", NULL, 1);
51
++        test_syslog_parse_identifier(":  ", "", NULL, 3);
52
++        test_syslog_parse_identifier("pidu:", "pidu", NULL, 5);
53
++        test_syslog_parse_identifier("pidu: ", "pidu", NULL, 6);
54
++        test_syslog_parse_identifier("pidu : ", NULL, NULL, 0);
55
+ 
56
+         return 0;
57
+ }
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          Systemd-233
2 2
 Name:             systemd
3 3
 Version:          233
4
-Release:          17%{?dist}
4
+Release:          18%{?dist}
5 5
 License:          LGPLv2+ and GPLv2+ and MIT
6 6
 URL:              http://www.freedesktop.org/wiki/Software/systemd/
7 7
 Group:            System Environment/Security
... ...
@@ -34,6 +34,9 @@ Patch15:          systemd-233-util-linux-build-failure.patch
34 34
 Patch16:          systemd-233-CVE-2018-1049.patch
35 35
 Patch17:          systemd-233-CVE-2018-15688.patch
36 36
 Patch18:          systemd-233-CVE-2018-15686.patch
37
+Patch19:          systemd-233-CVE-2018-16864.patch
38
+Patch20:          systemd-233-CVE-2018-16865.patch
39
+Patch21:          systemd-233-CVE-2018-16866.patch
37 40
 
38 41
 Requires:         Linux-PAM
39 42
 Requires:         libcap
... ...
@@ -106,6 +109,9 @@ sed -i "/xlocale.h/d" src/basic/parse-util.c
106 106
 %patch16 -p1
107 107
 %patch17 -p1
108 108
 %patch18 -p1
109
+%patch19 -p1
110
+%patch20 -p1
111
+%patch21 -p1
109 112
 
110 113
 sed -i "s#\#DefaultTasksMax=512#DefaultTasksMax=infinity#g" src/core/system.conf
111 114
 
... ...
@@ -256,6 +262,8 @@ rm -rf %{buildroot}/*
256 256
 %files lang -f %{name}.lang
257 257
 
258 258
 %changelog
259
+*    Thu Jan 10 2019 Anish Swaminathan <anishs@vmware.com>  233-18
260
+-    Fix CVE-2018-16864, CVE-2018-16865, CVE-2018-16866
259 261
 *    Thu Jan 03 2019 Anish Swaminathan <anishs@vmware.com>  233-17
260 262
 -    Fix CVE-2018-15686
261 263
 *    Fri Nov 02 2018 Tapas Kundu <tkundu@vmware.com> 233-16