Browse code

Fix for systemd CVE-2018-15686

Change-Id: If3f77d3b339e5c9631a21dd14f69ff9b3231e47c
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6449
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Alexey Makhalov <amakhalov@vmware.com>

suezzelur authored on 2019/01/05 04:42:18
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,362 @@
0
+diff -rup systemd-233/src/basic/fileio.c systemd-233-new/src/basic/fileio.c
1
+--- systemd-233/src/basic/fileio.c	2017-03-01 13:43:06.000000000 -0800
2
+@@ -164,21 +164,7 @@ int read_one_line_file(const char *fn, c
3
+         if (!f)
4
+                 return -errno;
5
+ 
6
+-        if (!fgets(t, sizeof(t), f)) {
7
+-
8
+-                if (ferror(f))
9
+-                        return errno > 0 ? -errno : -EIO;
10
+-
11
+-                t[0] = 0;
12
+-        }
13
+-
14
+-        c = strdup(t);
15
+-        if (!c)
16
+-                return -ENOMEM;
17
+-        truncate_nl(c);
18
+-
19
+-        *line = c;
20
+-        return 0;
21
++        return read_line(f, LONG_LINE_MAX, line);
22
+ }
23
+ 
24
+ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
25
+@@ -1489,3 +1475,75 @@ int mkdtemp_malloc(const char *template,
26
+         *ret = p;
27
+         return 0;
28
+ }
29
++
30
++DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, funlockfile);
31
++
32
++int read_line(FILE *f, size_t limit, char **ret) {
33
++        _cleanup_free_ char *buffer = NULL;
34
++        size_t n = 0, allocated = 0, count = 0;
35
++
36
++        assert(f);
37
++
38
++        /* Something like a bounded version of getline().
39
++         *
40
++         * Considers EOF, \n and \0 end of line delimiters, and does not include these delimiters in the string
41
++         * returned.
42
++         *
43
++         * Returns the number of bytes read from the files (i.e. including delimiters — this hence usually differs from
44
++         * the number of characters in the returned string). When EOF is hit, 0 is returned.
45
++         *
46
++         * The input parameter limit is the maximum numbers of characters in the returned string, i.e. excluding
47
++         * delimiters. If the limit is hit we fail and return -ENOBUFS.
48
++         *
49
++         * If a line shall be skipped ret may be initialized as NULL. */
50
++
51
++        if (ret) {
52
++                if (!GREEDY_REALLOC(buffer, allocated, 1))
53
++                        return -ENOMEM;
54
++        }
55
++
56
++        {
57
++                _unused_ _cleanup_(funlockfilep) FILE *flocked = f;
58
++                flockfile(f);
59
++
60
++                for (;;) {
61
++                        int c;
62
++
63
++                        if (n >= limit)
64
++                                return -ENOBUFS;
65
++
66
++                        errno = 0;
67
++                        c = fgetc_unlocked(f);
68
++                        if (c == EOF) {
69
++                                /* if we read an error, and have no data to return, then propagate the error */
70
++                                if (ferror_unlocked(f) && n == 0)
71
++                                        return errno > 0 ? -errno : -EIO;
72
++
73
++                                break;
74
++                        }
75
++
76
++                        count++;
77
++
78
++                        if (IN_SET(c, '\n', 0)) /* Reached a delimiter */
79
++                                break;
80
++
81
++                        if (ret) {
82
++                                if (!GREEDY_REALLOC(buffer, allocated, n + 2))
83
++                                        return -ENOMEM;
84
++
85
++                                buffer[n] = (char) c;
86
++                        }
87
++
88
++                        n++;
89
++                }
90
++        }
91
++
92
++        if (ret) {
93
++                buffer[n] = 0;
94
++
95
++                *ret = buffer;
96
++                buffer = NULL;
97
++        }
98
++
99
++        return (int) count;
100
++}
101
+diff -rup systemd-233/src/basic/fileio.h systemd-233-new/src/basic/fileio.h
102
+--- systemd-233/src/basic/fileio.h	2017-03-01 13:43:06.000000000 -0800
103
+@@ -28,6 +28,8 @@
104
+ #include "macro.h"
105
+ #include "time-util.h"
106
+ 
107
++#define LONG_LINE_MAX (1U*1024U*1024U)
108
++
109
+ typedef enum {
110
+         WRITE_STRING_FILE_CREATE = 1,
111
+         WRITE_STRING_FILE_ATOMIC = 2,
112
+@@ -93,3 +95,5 @@ int link_tmpfile(int fd, const char *pat
113
+ int read_nul_string(FILE *f, char **ret);
114
+ 
115
+ int mkdtemp_malloc(const char *template, char **ret);
116
++
117
++int read_line(FILE *f, size_t limit, char **ret);
118
+diff -rup systemd-233/src/core/job.c systemd-233-new/src/core/job.c
119
+--- systemd-233/src/core/job.c	2017-03-01 13:43:06.000000000 -0800
120
+@@ -27,6 +27,7 @@
121
+ #include "dbus-job.h"
122
+ #include "dbus.h"
123
+ #include "escape.h"
124
++#include "fileio.h"
125
+ #include "job.h"
126
+ #include "log.h"
127
+ #include "macro.h"
128
+@@ -1036,24 +1037,26 @@ int job_serialize(Job *j, FILE *f) {
129
+ }
130
+ 
131
+ int job_deserialize(Job *j, FILE *f) {
132
++        int r;
133
++
134
+         assert(j);
135
+         assert(f);
136
+ 
137
+         for (;;) {
138
+-                char line[LINE_MAX], *l, *v;
139
++                _cleanup_free_ char *line = NULL;
140
++                char *l, *v;
141
+                 size_t k;
142
+ 
143
+-                if (!fgets(line, sizeof(line), f)) {
144
+-                        if (feof(f))
145
+-                                return 0;
146
+-                        return -errno;
147
+-                }
148
++                r = read_line(f, LONG_LINE_MAX, &line);
149
++                if (r < 0)
150
++                        return log_error_errno(r, "Failed to read serialization line: %m");
151
++                if (r == 0)
152
++                        return 0;
153
+ 
154
+-                char_array_0(line);
155
+                 l = strstrip(line);
156
+ 
157
+                 /* End marker */
158
+-                if (l[0] == 0)
159
++                if (isempty(l))
160
+                         return 0;
161
+ 
162
+                 k = strcspn(l, "=");
163
+diff -rup systemd-233/src/core/manager.c systemd-233-new/src/core/manager.c
164
+--- systemd-233/src/core/manager.c	2017-03-01 13:43:06.000000000 -0800
165
+@@ -1298,8 +1298,11 @@ int manager_startup(Manager *m, FILE *se
166
+         dual_timestamp_get(&m->units_load_finish_timestamp);
167
+ 
168
+         /* Second, deserialize if there is something to deserialize */
169
+-        if (serialization)
170
++        if (serialization) {
171
+                 r = manager_deserialize(m, serialization, fds);
172
++                if (r < 0)
173
++                        log_error_errno(r, "Deserialization failed: %m");
174
++        }
175
+ 
176
+         /* Any fds left? Find some unit which wants them. This is
177
+          * useful to allow container managers to pass some file
178
+@@ -2585,22 +2588,19 @@ int manager_deserialize(Manager *m, FILE
179
+         m->n_reloading++;
180
+ 
181
+         for (;;) {
182
+-                char line[LINE_MAX], *l;
183
+-                const char *val;
184
+-
185
+-                if (!fgets(line, sizeof(line), f)) {
186
+-                        if (feof(f))
187
+-                                r = 0;
188
+-                        else
189
+-                                r = -errno;
190
++                _cleanup_free_ char *line = NULL;
191
++                const char *val, *l;
192
+ 
193
++                r = read_line(f, LONG_LINE_MAX, &line);
194
++                if (r < 0) {
195
++                        log_error_errno(r, "Failed to read serialization line: %m");
196
+                         goto finish;
197
+                 }
198
++                if (r == 0)
199
++                        break;
200
+ 
201
+-                char_array_0(line);
202
+                 l = strstrip(line);
203
+-
204
+-                if (l[0] == 0)
205
++                if (isempty(l)) /* end marker */
206
+                         break;
207
+ 
208
+                 if ((val = startswith(l, "current-job-id="))) {
209
+@@ -2727,34 +2727,43 @@ int manager_deserialize(Manager *m, FILE
210
+         }
211
+ 
212
+         for (;;) {
213
++                _cleanup_free_ char *line = NULL;
214
++                const char* unit_name;
215
+                 Unit *u;
216
+-                char name[UNIT_NAME_MAX+2];
217
+ 
218
+                 /* Start marker */
219
+-                if (!fgets(name, sizeof(name), f)) {
220
+-                        if (feof(f))
221
+-                                r = 0;
222
+-                        else
223
+-                                r = -errno;
224
+-
225
++                r = read_line(f, LONG_LINE_MAX, &line);
226
++                if (r < 0) {
227
++                        log_error_errno(r, "Failed to read serialization line: %m");
228
+                         goto finish;
229
+                 }
230
++                if (r == 0)
231
++                        break;
232
+ 
233
+-                char_array_0(name);
234
++                unit_name = strstrip(line);
235
+ 
236
+-                r = manager_load_unit(m, strstrip(name), NULL, NULL, &u);
237
+-                if (r < 0)
238
+-                        goto finish;
239
++                r = manager_load_unit(m, unit_name, NULL, NULL, &u);
240
++                if (r < 0) {
241
++                        log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name);
242
++                        if (r == -ENOMEM)
243
++                                goto finish;
244
++
245
++                        r = unit_deserialize_skip(f);
246
++                        if (r < 0)
247
++                                goto finish;
248
++
249
++                        continue;
250
++                }
251
+ 
252
+                 r = unit_deserialize(u, f, fds);
253
+-                if (r < 0)
254
+-                        goto finish;
255
++                if (r < 0) {
256
++                        log_notice_errno(r, "Failed to deserialize unit \"%s\": %m", unit_name);
257
++                        if (r == -ENOMEM)
258
++                                goto finish;
259
++                }
260
+         }
261
+ 
262
+ finish:
263
+-        if (ferror(f))
264
+-                r = -EIO;
265
+-
266
+         assert(m->n_reloading > 0);
267
+         m->n_reloading--;
268
+ 
269
+@@ -2821,8 +2830,12 @@ int manager_reload(Manager *m) {
270
+ 
271
+         /* Second, deserialize our stored data */
272
+         q = manager_deserialize(m, f, fds);
273
+-        if (q < 0 && r >= 0)
274
+-                r = q;
275
++        if (q < 0) {
276
++                log_error_errno(q, "Deserialization failed: %m");
277
++
278
++                 if (r >= 0)
279
++                        r = q;
280
++        }
281
+ 
282
+         fclose(f);
283
+         f = NULL;
284
+diff -rup systemd-233/src/core/unit.c systemd-233-new/src/core/unit.c
285
+--- systemd-233/src/core/unit.c	2017-03-01 13:43:06.000000000 -0800
286
+@@ -2856,20 +2856,20 @@ int unit_deserialize(Unit *u, FILE *f, F
287
+                 rt = (ExecRuntime**) ((uint8_t*) u + offset);
288
+ 
289
+         for (;;) {
290
+-                char line[LINE_MAX], *l, *v;
291
++                _cleanup_free_ char *line = NULL;
292
++                char *l, *v;
293
+                 size_t k;
294
+ 
295
+-                if (!fgets(line, sizeof(line), f)) {
296
+-                        if (feof(f))
297
+-                                return 0;
298
+-                        return -errno;
299
+-                }
300
++                r = read_line(f, LONG_LINE_MAX, &line);
301
++                if (r < 0)
302
++                        return log_error_errno(r, "Failed to read serialization line: %m");
303
++                if (r == 0) /* eof */
304
++                        break;
305
+ 
306
+-                char_array_0(line);
307
+                 l = strstrip(line);
308
+ 
309
+                 /* End marker */
310
+-                if (isempty(l))
311
++                if (isempty(l)) /* End marker */
312
+                         break;
313
+ 
314
+                 k = strcspn(l, "=");
315
+@@ -3068,6 +3068,30 @@ int unit_deserialize(Unit *u, FILE *f, F
316
+         return 0;
317
+ }
318
+ 
319
++int unit_deserialize_skip(FILE *f) {
320
++        int r;
321
++        assert(f);
322
++
323
++        /* Skip serialized data for this unit. We don't know what it is. */
324
++
325
++        for (;;) {
326
++                _cleanup_free_ char *line = NULL;
327
++                char *l;
328
++
329
++                r = read_line(f, LONG_LINE_MAX, &line);
330
++                if (r < 0)
331
++                        return log_error_errno(r, "Failed to read serialization line: %m");
332
++                if (r == 0)
333
++                        return 0;
334
++
335
++                l = strstrip(line);
336
++
337
++                /* End marker */
338
++                if (isempty(l))
339
++                        return 1;
340
++        }
341
++}
342
++
343
+ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency dep) {
344
+         Unit *device;
345
+         _cleanup_free_ char *e = NULL;
346
+diff -rup systemd-233/src/core/unit.h systemd-233-new/src/core/unit.h
347
+--- systemd-233/src/core/unit.h	2017-03-01 13:43:06.000000000 -0800
348
+@@ -564,6 +564,7 @@ bool unit_can_serialize(Unit *u) _pure_;
349
+ 
350
+ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
351
+ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
352
++int unit_deserialize_skip(FILE *f);
353
+ 
354
+ int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
355
+ int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          Systemd-233
2 2
 Name:             systemd
3 3
 Version:          233
4
-Release:          16%{?dist}
4
+Release:          17%{?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
... ...
@@ -33,6 +33,7 @@ Patch14:          systemd-233-CVE-2017-18078.patch
33 33
 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
+Patch18:          systemd-233-CVE-2018-15686.patch
36 37
 
37 38
 Requires:         Linux-PAM
38 39
 Requires:         libcap
... ...
@@ -104,6 +105,7 @@ sed -i "/xlocale.h/d" src/basic/parse-util.c
104 104
 %patch15 -p1
105 105
 %patch16 -p1
106 106
 %patch17 -p1
107
+%patch18 -p1
107 108
 
108 109
 sed -i "s#\#DefaultTasksMax=512#DefaultTasksMax=infinity#g" src/core/system.conf
109 110
 
... ...
@@ -254,6 +256,8 @@ rm -rf %{buildroot}/*
254 254
 %files lang -f %{name}.lang
255 255
 
256 256
 %changelog
257
+*    Thu Jan 03 2019 Anish Swaminathan <anishs@vmware.com>  233-17
258
+-    Fix CVE-2018-15686
257 259
 *    Fri Nov 02 2018 Tapas Kundu <tkundu@vmware.com> 233-16
258 260
 -    Fix CVE-2018-15688
259 261
 *    Mon Jul 23 2018 Ankit Jain <ankitja@vmware.com>  233-15
... ...
@@ -274,7 +278,7 @@ rm -rf %{buildroot}/*
274 274
 -    Move network file to systemd package
275 275
 *    Tue Aug 15 2017 Alexey Makhalov <amakhalov@vmware.com> 233-7
276 276
 -    Fix compilation issue for glibc-2.26
277
-*    Fri Jul 20 2017 Vinay Kulkarni <kulkarniv@vmware.com>  233-6
277
+*    Thu Jul 20 2017 Vinay Kulkarni <kulkarniv@vmware.com>  233-6
278 278
 -    Fix for CVE-2017-1000082.
279 279
 *    Fri Jul 07 2017 Vinay Kulkarni <kulkarniv@vmware.com>  233-5
280 280
 -    Fix default-dns-from-env patch.