Browse code

Fix systemd CVE-2018-15686 and CVE-2018-15687

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

suezzelur authored on 2019/01/04 06:55:53
Showing 6 changed files
1 1
deleted file mode 100644
... ...
@@ -1,23 +0,0 @@
1
-diff -uNr systemd-233/src/resolve/resolved-conf.c systemd-233-new/src/resolve/resolved-conf.c
2
-+++ systemd-233-new/src/resolve/resolved-conf.c	2017-07-07 03:29:00.130502439 +0000
3
-@@ -229,6 +229,7 @@
4
- 
5
- int manager_parse_config_file(Manager *m) {
6
-         int r;
7
-+        char *default_dns_servers;
8
- 
9
-         assert(m);
10
- 
11
-@@ -241,7 +242,10 @@
12
-                 return r;
13
- 
14
-         if (m->need_builtin_fallbacks) {
15
--                r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
16
-+                default_dns_servers = secure_getenv("DEFAULT_DNS_SERVERS");
17
-+                if (default_dns_servers == NULL)
18
-+                        default_dns_servers = DNS_SERVERS;
19
-+                r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, default_dns_servers);
20
-                 if (r < 0)
21
-                         return r;
22
-         }
23 1
deleted file mode 100644
... ...
@@ -1,72 +0,0 @@
1
-From 227b8a762fea1458547be2cdf0e6e4aac0079730 Mon Sep 17 00:00:00 2001
2
-From: Michael Olbrich <m.olbrich@pengutronix.de>
3
-Date: Mon, 26 Mar 2018 17:34:53 +0200
4
-Subject: [PATCH] core: don't include libmount.h in a header file (#8580)
5
-
6
-linux/fs.h sys/mount.h, libmount.h and missing.h all include MS_*
7
-definitions.
8
-
9
-To avoid problems, only one of linux/fs.h, sys/mount.h and libmount.h
10
-should be included. And missing.h must be included last.
11
-
12
-Without this, building systemd may fail with:
13
-
14
-In file included from [...]/libmount/libmount.h:31:0,
15
-                 from ../systemd-238/src/core/manager.h:23,
16
-                 from ../systemd-238/src/core/emergency-action.h:37,
17
-                 from ../systemd-238/src/core/unit.h:34,
18
-                 from ../systemd-238/src/core/dbus-timer.h:25,
19
-                 from ../systemd-238/src/core/timer.c:26:
20
-[...]/sys/mount.h:57:2: error: expected identifier before numeric constant
21
- src/core/dbus-execute.c | 1 +
22
- src/core/manager.h      | 3 ++-
23
- src/core/mount.c        | 2 ++
24
- 3 files changed, 5 insertions(+), 1 deletion(-)
25
-
26
-diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
27
-index 7344623ebf6..c342093bca4 100644
28
-+++ b/src/core/dbus-execute.c
29
-@@ -18,6 +18,7 @@
30
-   along with systemd; If not, see <http://www.gnu.org/licenses/>.
31
- ***/
32
- 
33
-+#include <sys/mount.h>
34
- #include <sys/prctl.h>
35
- #include <stdio_ext.h>
36
- 
37
-diff --git a/src/core/manager.h b/src/core/manager.h
38
-index 28c5da225b1..e09e0cdf5e9 100644
39
-+++ b/src/core/manager.h
40
-@@ -20,7 +20,6 @@
41
-   along with systemd; If not, see <http://www.gnu.org/licenses/>.
42
- ***/
43
- 
44
--#include <libmount.h>
45
- #include <stdbool.h>
46
- #include <stdio.h>
47
- 
48
-@@ -34,6 +33,8 @@
49
- #include "list.h"
50
- #include "ratelimit.h"
51
- 
52
-+struct libmnt_monitor;
53
-+
54
- /* Enforce upper limit how many names we allow */
55
- #define MANAGER_MAX_NAMES 131072 /* 128K */
56
- 
57
-diff --git a/src/core/mount.c b/src/core/mount.c
58
-index 0e755da5c02..0154ebda5d6 100644
59
-+++ b/src/core/mount.c
60
-@@ -23,6 +23,8 @@
61
- #include <stdio.h>
62
- #include <sys/epoll.h>
63
- 
64
-+#include <libmount.h>
65
-+
66
- #include "sd-messages.h"
67
- 
68
- #include "alloc-util.h"
69 1
new file mode 100644
... ...
@@ -0,0 +1,242 @@
0
+From 1a05ff4948d778280ec155a9abe69d3360bfddd9 Mon Sep 17 00:00:00 2001
1
+From: Lennart Poettering <lennart@poettering.net>
2
+Date: Wed, 17 Oct 2018 18:36:24 +0200
3
+Subject: [PATCH] =?UTF-8?q?core:=20when=20deserializing=20state=20always?=
4
+ =?UTF-8?q?=20use=20read=5Fline(=E2=80=A6,=20LONG=5FLINE=5FMAX,=20?=
5
+ =?UTF-8?q?=E2=80=A6)?=
6
+MIME-Version: 1.0
7
+Content-Type: text/plain; charset=UTF-8
8
+Content-Transfer-Encoding: 8bit
9
+
10
+This should be much better than fgets(), as we can read substantially
11
+longer lines and overly long lines result in proper errors.
12
+
13
+Fixes a vulnerability discovered by Jann Horn at Google.
14
+
15
+CVE-2018-15686
16
+LP: #1796402
17
+https://bugzilla.redhat.com/show_bug.cgi?id=1639071
18
+
19
+(cherry picked from commit 8948b3415d762245ebf5e19d80b97d4d8cc208c1)
20
+---
21
+ src/core/job.c     | 19 +++++++++++--------
22
+ src/core/manager.c | 44 ++++++++++++++++++++------------------------
23
+ src/core/unit.c    | 34 ++++++++++++++++++----------------
24
+ src/core/unit.h    |  2 +-
25
+ 4 files changed, 50 insertions(+), 49 deletions(-)
26
+
27
+diff --git a/src/core/job.c b/src/core/job.c
28
+index 734756b666..8552ffb704 100644
29
+--- a/src/core/job.c
30
+@@ -10,6 +10,7 @@
31
+ #include "dbus-job.h"
32
+ #include "dbus.h"
33
+ #include "escape.h"
34
++#include "fileio.h"
35
+ #include "job.h"
36
+ #include "log.h"
37
+ #include "macro.h"
38
+@@ -1091,24 +1092,26 @@ int job_serialize(Job *j, FILE *f) {
39
+ }
40
+ 
41
+ int job_deserialize(Job *j, FILE *f) {
42
++        int r;
43
++
44
+         assert(j);
45
+         assert(f);
46
+ 
47
+         for (;;) {
48
+-                char line[LINE_MAX], *l, *v;
49
++                _cleanup_free_ char *line = NULL;
50
++                char *l, *v;
51
+                 size_t k;
52
+ 
53
+-                if (!fgets(line, sizeof(line), f)) {
54
+-                        if (feof(f))
55
+-                                return 0;
56
+-                        return -errno;
57
+-                }
58
++                r = read_line(f, LONG_LINE_MAX, &line);
59
++                if (r < 0)
60
++                        return log_error_errno(r, "Failed to read serialization line: %m");
61
++                if (r == 0)
62
++                        return 0;
63
+ 
64
+-                char_array_0(line);
65
+                 l = strstrip(line);
66
+ 
67
+                 /* End marker */
68
+-                if (l[0] == 0)
69
++                if (isempty(l))
70
+                         return 0;
71
+ 
72
+                 k = strcspn(l, "=");
73
+diff --git a/src/core/manager.c b/src/core/manager.c
74
+index 3a7f0c41b2..a5780c9440 100644
75
+--- a/src/core/manager.c
76
+@@ -3171,22 +3171,19 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
77
+         m->n_reloading++;
78
+ 
79
+         for (;;) {
80
+-                char line[LINE_MAX];
81
++                _cleanup_free_ char *line = NULL;
82
+                 const char *val, *l;
83
+ 
84
+-                if (!fgets(line, sizeof(line), f)) {
85
+-                        if (feof(f))
86
+-                                r = 0;
87
+-                        else
88
+-                                r = -errno;
89
+-
90
++                r = read_line(f, LONG_LINE_MAX, &line);
91
++                if (r < 0) {
92
++                        log_error_errno(r, "Failed to read serialization line: %m");
93
+                         goto finish;
94
+                 }
95
++                if (r == 0)
96
++                        break;
97
+ 
98
+-                char_array_0(line);
99
+                 l = strstrip(line);
100
+-
101
+-                if (l[0] == 0)
102
++                if (isempty(l)) /* end marker */
103
+                         break;
104
+ 
105
+                 if ((val = startswith(l, "current-job-id="))) {
106
+@@ -3353,29 +3350,31 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
107
+         }
108
+ 
109
+         for (;;) {
110
+-                Unit *u;
111
+-                char name[UNIT_NAME_MAX+2];
112
++                _cleanup_free_ char *line = NULL;
113
+                 const char* unit_name;
114
++                Unit *u;
115
+ 
116
+                 /* Start marker */
117
+-                if (!fgets(name, sizeof(name), f)) {
118
+-                        if (feof(f))
119
+-                                r = 0;
120
+-                        else
121
+-                                r = -errno;
122
+-
123
++                r = read_line(f, LONG_LINE_MAX, &line);
124
++                if (r < 0) {
125
++                        log_error_errno(r, "Failed to read serialization line: %m");
126
+                         goto finish;
127
+                 }
128
++                if (r == 0)
129
++                        break;
130
+ 
131
+-                char_array_0(name);
132
+-                unit_name = strstrip(name);
133
++                unit_name = strstrip(line);
134
+ 
135
+                 r = manager_load_unit(m, unit_name, NULL, NULL, &u);
136
+                 if (r < 0) {
137
+                         log_notice_errno(r, "Failed to load unit \"%s\", skipping deserialization: %m", unit_name);
138
+                         if (r == -ENOMEM)
139
+                                 goto finish;
140
+-                        unit_deserialize_skip(f);
141
++
142
++                        r = unit_deserialize_skip(f);
143
++                        if (r < 0)
144
++                                goto finish;
145
++
146
+                         continue;
147
+                 }
148
+ 
149
+@@ -3388,9 +3387,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
150
+         }
151
+ 
152
+ finish:
153
+-        if (ferror(f))
154
+-                r = -EIO;
155
+-
156
+         assert(m->n_reloading > 0);
157
+         m->n_reloading--;
158
+ 
159
+diff --git a/src/core/unit.c b/src/core/unit.c
160
+index 7da963a9b7..e98c9c4099 100644
161
+--- a/src/core/unit.c
162
+@@ -3380,21 +3380,19 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
163
+         assert(fds);
164
+ 
165
+         for (;;) {
166
+-                char line[LINE_MAX], *l, *v;
167
++                _cleanup_free_ char *line = NULL;
168
+                 CGroupIPAccountingMetric m;
169
++                char *l, *v;
170
+                 size_t k;
171
+ 
172
+-                if (!fgets(line, sizeof(line), f)) {
173
+-                        if (feof(f))
174
+-                                return 0;
175
+-                        return -errno;
176
+-                }
177
++                r = read_line(f, LONG_LINE_MAX, &line);
178
++                if (r < 0)
179
++                        return log_error_errno(r, "Failed to read serialization line: %m");
180
++                if (r == 0) /* eof */
181
++                        break;
182
+ 
183
+-                char_array_0(line);
184
+                 l = strstrip(line);
185
+-
186
+-                /* End marker */
187
+-                if (isempty(l))
188
++                if (isempty(l)) /* End marker */
189
+                         break;
190
+ 
191
+                 k = strcspn(l, "=");
192
+@@ -3671,23 +3669,27 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {
193
+         return 0;
194
+ }
195
+ 
196
+-void unit_deserialize_skip(FILE *f) {
197
++int unit_deserialize_skip(FILE *f) {
198
++        int r;
199
+         assert(f);
200
+ 
201
+         /* Skip serialized data for this unit. We don't know what it is. */
202
+ 
203
+         for (;;) {
204
+-                char line[LINE_MAX], *l;
205
++                _cleanup_free_ char *line = NULL;
206
++                char *l;
207
+ 
208
+-                if (!fgets(line, sizeof line, f))
209
+-                        return;
210
++                r = read_line(f, LONG_LINE_MAX, &line);
211
++                if (r < 0)
212
++                        return log_error_errno(r, "Failed to read serialization line: %m");
213
++                if (r == 0)
214
++                        return 0;
215
+ 
216
+-                char_array_0(line);
217
+                 l = strstrip(line);
218
+ 
219
+                 /* End marker */
220
+                 if (isempty(l))
221
+-                        return;
222
++                        return 1;
223
+         }
224
+ }
225
+ 
226
+diff --git a/src/core/unit.h b/src/core/unit.h
227
+index 06321bb39c..51c7aaae39 100644
228
+--- a/src/core/unit.h
229
+@@ -684,7 +684,7 @@ bool unit_can_serialize(Unit *u) _pure_;
230
+ 
231
+ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs);
232
+ int unit_deserialize(Unit *u, FILE *f, FDSet *fds);
233
+-void unit_deserialize_skip(FILE *f);
234
++int unit_deserialize_skip(FILE *f);
235
+ 
236
+ int unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value);
237
+ int unit_serialize_item_escaped(Unit *u, FILE *f, const char *key, const char *value);
0 238
new file mode 100644
... ...
@@ -0,0 +1,298 @@
0
+From 5de6cce58b3e8b79239b6e83653459d91af6e57c Mon Sep 17 00:00:00 2001
1
+From: Lennart Poettering <lennart@poettering.net>
2
+Date: Fri, 19 Oct 2018 11:26:59 +0200
3
+Subject: [PATCH 1/4] chown-recursive: let's rework the recursive logic to use
4
+ O_PATH
5
+
6
+That way we can pin a specific inode and analyze it and manipulate it
7
+without it being swapped out beneath our hands.
8
+
9
+Fixes a vulnerability originally found by Jann Horn from Google.
10
+
11
+CVE-2018-15687
12
+LP: #1796692
13
+https://bugzilla.redhat.com/show_bug.cgi?id=1639076
14
+---
15
+ src/core/chown-recursive.c | 146 ++++++++++++++++++-------------------
16
+ 1 file changed, 70 insertions(+), 76 deletions(-)
17
+
18
+diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c
19
+index c4794501c2c..27c64489b55 100644
20
+--- a/src/core/chown-recursive.c
21
+@@ -1,17 +1,19 @@
22
+ /* SPDX-License-Identifier: LGPL-2.1+ */
23
+ 
24
+-#include <sys/types.h>
25
+-#include <sys/stat.h>
26
+ #include <fcntl.h>
27
++#include <sys/stat.h>
28
++#include <sys/types.h>
29
+ 
30
+-#include "user-util.h"
31
+-#include "macro.h"
32
+-#include "fd-util.h"
33
+-#include "dirent-util.h"
34
+ #include "chown-recursive.h"
35
++#include "dirent-util.h"
36
++#include "fd-util.h"
37
++#include "macro.h"
38
++#include "stdio-util.h"
39
++#include "strv.h"
40
++#include "user-util.h"
41
+ 
42
+-static int chown_one(int fd, const char *name, const struct stat *st, uid_t uid, gid_t gid) {
43
+-        int r;
44
++static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) {
45
++        char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
46
+ 
47
+         assert(fd >= 0);
48
+         assert(st);
49
+@@ -20,90 +22,82 @@ static int chown_one(int fd, const char *name, const struct stat *st, uid_t uid,
50
+             (!gid_is_valid(gid) || st->st_gid == gid))
51
+                 return 0;
52
+ 
53
+-        if (name)
54
+-                r = fchownat(fd, name, uid, gid, AT_SYMLINK_NOFOLLOW);
55
+-        else
56
+-                r = fchown(fd, uid, gid);
57
+-        if (r < 0)
58
+-                return -errno;
59
++        /* We change ownership through the /proc/self/fd/%i path, so that we have a stable reference that works with
60
++         * O_PATH. (Note: fchown() and fchmod() do not work with O_PATH, the kernel refuses that. */
61
++        xsprintf(procfs_path, "/proc/self/fd/%i", fd);
62
+ 
63
+-        /* The linux kernel alters the mode in some cases of chown(). Let's undo this. */
64
+-        if (name) {
65
+-                if (!S_ISLNK(st->st_mode))
66
+-                        r = fchmodat(fd, name, st->st_mode, 0);
67
+-                else /* There's currently no AT_SYMLINK_NOFOLLOW for fchmodat() */
68
+-                        r = 0;
69
+-        } else
70
+-                r = fchmod(fd, st->st_mode);
71
+-        if (r < 0)
72
++        if (chown(procfs_path, uid, gid) < 0)
73
+                 return -errno;
74
+ 
75
++        /* The linux kernel alters the mode in some cases of chown(). Let's undo this. We do this only for non-symlinks
76
++         * however. That's because for symlinks the access mode is ignored anyway and because on some kernels/file
77
++         * systems trying to change the access mode will succeed but has no effect while on others it actively
78
++         * fails. */
79
++        if (!S_ISLNK(st->st_mode))
80
++                if (chmod(procfs_path, st->st_mode & 07777) < 0)
81
++                        return -errno;
82
++
83
+         return 1;
84
+ }
85
+ 
86
+ static int chown_recursive_internal(int fd, const struct stat *st, uid_t uid, gid_t gid) {
87
++        _cleanup_closedir_ DIR *d = NULL;
88
+         bool changed = false;
89
++        struct dirent *de;
90
+         int r;
91
+ 
92
+         assert(fd >= 0);
93
+         assert(st);
94
+ 
95
+-        if (S_ISDIR(st->st_mode)) {
96
+-                _cleanup_closedir_ DIR *d = NULL;
97
+-                struct dirent *de;
98
+-
99
+-                d = fdopendir(fd);
100
+-                if (!d) {
101
+-                        r = -errno;
102
+-                        goto finish;
103
+-                }
104
+-                fd = -1;
105
+-
106
+-                FOREACH_DIRENT_ALL(de, d, r = -errno; goto finish) {
107
+-                        struct stat fst;
108
+-
109
+-                        if (dot_or_dot_dot(de->d_name))
110
+-                                continue;
111
+-
112
+-                        if (fstatat(dirfd(d), de->d_name, &fst, AT_SYMLINK_NOFOLLOW) < 0) {
113
+-                                r = -errno;
114
+-                                goto finish;
115
+-                        }
116
+-
117
+-                        if (S_ISDIR(fst.st_mode)) {
118
+-                                int subdir_fd;
119
+-
120
+-                                subdir_fd = openat(dirfd(d), de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
121
+-                                if (subdir_fd < 0) {
122
+-                                        r = -errno;
123
+-                                        goto finish;
124
+-                                }
125
+-
126
+-                                r = chown_recursive_internal(subdir_fd, &fst, uid, gid);
127
+-                                if (r < 0)
128
+-                                        goto finish;
129
+-                                if (r > 0)
130
+-                                        changed = true;
131
+-                        } else {
132
+-                                r = chown_one(dirfd(d), de->d_name, &fst, uid, gid);
133
+-                                if (r < 0)
134
+-                                        goto finish;
135
+-                                if (r > 0)
136
+-                                        changed = true;
137
+-                        }
138
++        d = fdopendir(fd);
139
++        if (!d) {
140
++                safe_close(fd);
141
++                return -errno;
142
++        }
143
++
144
++        FOREACH_DIRENT_ALL(de, d, return -errno) {
145
++                _cleanup_close_ int path_fd = -1;
146
++                struct stat fst;
147
++
148
++                if (dot_or_dot_dot(de->d_name))
149
++                        continue;
150
++
151
++                /* Let's pin the child inode we want to fix now with an O_PATH fd, so that it cannot be swapped out
152
++                 * while we manipulate it. */
153
++                path_fd = openat(dirfd(d), de->d_name, O_PATH|O_CLOEXEC|O_NOFOLLOW);
154
++                if (path_fd < 0)
155
++                        return -errno;
156
++
157
++                if (fstat(path_fd, &fst) < 0)
158
++                        return -errno;
159
++
160
++                if (S_ISDIR(fst.st_mode)) {
161
++                        int subdir_fd;
162
++
163
++                        /* Convert it to a "real" (i.e. non-O_PATH) fd now */
164
++                        subdir_fd = fd_reopen(path_fd, O_RDONLY|O_CLOEXEC|O_NOATIME);
165
++                        if (subdir_fd < 0)
166
++                                return subdir_fd;
167
++
168
++                        r = chown_recursive_internal(subdir_fd, &fst, uid, gid); /* takes possession of subdir_fd even on failure */
169
++                        if (r < 0)
170
++                                return r;
171
++                        if (r > 0)
172
++                                changed = true;
173
++                } else {
174
++                        r = chown_one(path_fd, &fst, uid, gid);
175
++                        if (r < 0)
176
++                                return r;
177
++                        if (r > 0)
178
++                                changed = true;
179
+                 }
180
++        }
181
+ 
182
+-                r = chown_one(dirfd(d), NULL, st, uid, gid);
183
+-        } else
184
+-                r = chown_one(fd, NULL, st, uid, gid);
185
++        r = chown_one(dirfd(d), st, uid, gid);
186
+         if (r < 0)
187
+-                goto finish;
188
++                return r;
189
+ 
190
+-        r = r > 0 || changed;
191
+-
192
+-finish:
193
+-        safe_close(fd);
194
+-        return r;
195
++        return r > 0 || changed;
196
+ }
197
+ 
198
+ int path_chown_recursive(const char *path, uid_t uid, gid_t gid) {
199
+@@ -111,7 +105,7 @@ int path_chown_recursive(const char *path, uid_t uid, gid_t gid) {
200
+         struct stat st;
201
+         int r;
202
+ 
203
+-        fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
204
++        fd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
205
+         if (fd < 0)
206
+                 return -errno;
207
+ 
208
+
209
+From f89bc84f3242449cbc308892c87573b131f121df Mon Sep 17 00:00:00 2001
210
+From: Lennart Poettering <lennart@poettering.net>
211
+Date: Fri, 19 Oct 2018 11:28:40 +0200
212
+Subject: [PATCH 2/4] chown-recursive: also drop ACLs when recursively
213
+ chown()ing
214
+
215
+Let's better be safe than sorry and also drop ACLs.
216
+---
217
+ src/core/chown-recursive.c | 16 ++++++++++++----
218
+ 1 file changed, 12 insertions(+), 4 deletions(-)
219
+
220
+diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c
221
+index 27c64489b55..447b7712676 100644
222
+--- a/src/core/chown-recursive.c
223
+@@ -3,6 +3,7 @@
224
+ #include <fcntl.h>
225
+ #include <sys/stat.h>
226
+ #include <sys/types.h>
227
++#include <sys/xattr.h>
228
+ 
229
+ #include "chown-recursive.h"
230
+ #include "dirent-util.h"
231
+@@ -14,6 +15,7 @@
232
+ 
233
+ static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) {
234
+         char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
235
++        const char *n;
236
+ 
237
+         assert(fd >= 0);
238
+         assert(st);
239
+@@ -26,13 +28,19 @@ static int chown_one(int fd, const struct stat *st, uid_t uid, gid_t gid) {
240
+          * O_PATH. (Note: fchown() and fchmod() do not work with O_PATH, the kernel refuses that. */
241
+         xsprintf(procfs_path, "/proc/self/fd/%i", fd);
242
+ 
243
++        /* Drop any ACL if there is one */
244
++        FOREACH_STRING(n, "system.posix_acl_access", "system.posix_acl_default")
245
++                if (removexattr(procfs_path, n) < 0)
246
++                        if (!IN_SET(errno, ENODATA, EOPNOTSUPP, ENOSYS, ENOTTY))
247
++                                return -errno;
248
++
249
+         if (chown(procfs_path, uid, gid) < 0)
250
+                 return -errno;
251
+ 
252
+-        /* The linux kernel alters the mode in some cases of chown(). Let's undo this. We do this only for non-symlinks
253
+-         * however. That's because for symlinks the access mode is ignored anyway and because on some kernels/file
254
+-         * systems trying to change the access mode will succeed but has no effect while on others it actively
255
+-         * fails. */
256
++        /* The linux kernel alters the mode in some cases of chown(), as well when we change ACLs. Let's undo this. We
257
++         * do this only for non-symlinks however. That's because for symlinks the access mode is ignored anyway and
258
++         * because on some kernels/file systems trying to change the access mode will succeed but has no effect while
259
++         * on others it actively fails. */
260
+         if (!S_ISLNK(st->st_mode))
261
+                 if (chmod(procfs_path, st->st_mode & 07777) < 0)
262
+                         return -errno;
263
+
264
+From cd6b7d50c337b3676a3d5fc2188ff298dcbdb939 Mon Sep 17 00:00:00 2001
265
+From: Lennart Poettering <lennart@poettering.net>
266
+Date: Fri, 19 Oct 2018 11:42:11 +0200
267
+Subject: [PATCH 3/4] chown-recursive: TAKE_FD() is your friend
268
+
269
+---
270
+ src/core/chown-recursive.c | 6 +-----
271
+ 1 file changed, 1 insertion(+), 5 deletions(-)
272
+
273
+diff --git a/src/core/chown-recursive.c b/src/core/chown-recursive.c
274
+index 447b7712676..7767301f7d9 100644
275
+--- a/src/core/chown-recursive.c
276
+@@ -111,7 +111,6 @@ static int chown_recursive_internal(int fd, const struct stat *st, uid_t uid, gi
277
+ int path_chown_recursive(const char *path, uid_t uid, gid_t gid) {
278
+         _cleanup_close_ int fd = -1;
279
+         struct stat st;
280
+-        int r;
281
+ 
282
+         fd = open(path, O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
283
+         if (fd < 0)
284
+@@ -130,8 +129,5 @@ int path_chown_recursive(const char *path, uid_t uid, gid_t gid) {
285
+             (!gid_is_valid(gid) || st.st_gid == gid))
286
+                 return 0;
287
+ 
288
+-        r = chown_recursive_internal(fd, &st, uid, gid);
289
+-        fd = -1; /* we donated the fd to the call, regardless if it succeeded or failed */
290
+-
291
+-        return r;
292
++        return chown_recursive_internal(TAKE_FD(fd), &st, uid, gid); /* we donate the fd to the call, regardless if it succeeded or failed */
293
+ }
294
+
0 295
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+diff -uNr systemd-233/src/resolve/resolved-conf.c systemd-233-new/src/resolve/resolved-conf.c
1
+--- systemd-233/src/resolve/resolved-conf.c	2017-03-01 21:43:06.000000000 +0000
2
+@@ -229,6 +229,7 @@
3
+ 
4
+ int manager_parse_config_file(Manager *m) {
5
+         int r;
6
++        char *default_dns_servers;
7
+ 
8
+         assert(m);
9
+ 
10
+@@ -241,7 +242,10 @@
11
+                 return r;
12
+ 
13
+         if (m->need_builtin_fallbacks) {
14
+-                r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
15
++                default_dns_servers = secure_getenv("DEFAULT_DNS_SERVERS");
16
++                if (default_dns_servers == NULL)
17
++                        default_dns_servers = DNS_SERVERS;
18
++                r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_FALLBACK, default_dns_servers);
19
+                 if (r < 0)
20
+                         return r;
21
+         }
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          Systemd-239
2 2
 Name:             systemd
3 3
 Version:          239
4
-Release:          7%{?dist}
4
+Release:          8%{?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
... ...
@@ -17,13 +17,15 @@ Source5:          10-rdrand-rng.conf
17 17
 
18 18
 Patch0:           01-enoX-uses-instance-number-for-vmware-hv.patch
19 19
 Patch1:           02-install-general-aliases.patch
20
-Patch2:           systemd-236-default-dns-from-env.patch
20
+Patch2:           systemd-239-default-dns-from-env.patch
21 21
 Patch3:           systemd-macros.patch
22 22
 Patch4:           systemd-239-query-duid.patch
23 23
 # Fix glibc-2.28 build issue. Checked in upstream after v239
24 24
 Patch5:           systemd-239-glibc-build-fix.patch
25 25
 Patch6:           systemd-239-revert-mtu.patch
26 26
 Patch7:           systemd-239-CVE-2018-15688.patch
27
+Patch8:           systemd-239-CVE-2018-15686.patch
28
+Patch9:           systemd-239-CVE-2018-15687.patch
27 29
 
28 30
 Requires:         Linux-PAM
29 31
 Requires:         libcap
... ...
@@ -86,6 +88,8 @@ EOF
86 86
 %patch5 -p1
87 87
 %patch6 -p1
88 88
 %patch7 -p1
89
+%patch8 -p1
90
+%patch9 -p1
89 91
 
90 92
 sed -i "s#\#DefaultTasksMax=512#DefaultTasksMax=infinity#g" src/core/system.conf.in
91 93
 
... ...
@@ -252,6 +256,8 @@ rm -rf %{buildroot}/*
252 252
 %files lang -f %{name}.lang
253 253
 
254 254
 %changelog
255
+*    Wed Jan 02 2019 Anish Swaminathan <anishs@vmware.com>  239-8
256
+-    Fix CVE-2018-15686, CVE-2018-15687
255 257
 *    Sun Nov 11 2018 Tapas Kundu <tkundu@vmware.com> 239-7
256 258
 -    Fix CVE-2018-15688
257 259
 *    Fri Oct 26 2018 Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu> 239-6