Browse code

Fix systemd CVE-2017-1000082

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

Vinay Kulkarni authored on 2017/07/21 08:36:35
Showing 3 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,305 @@
0
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
1
+index 6a6dadda2b..49a5c53f96 100644
2
+--- a/src/core/load-fragment.c
3
+@@ -636,26 +636,36 @@ int config_parse_exec(
4
+ 
5
+                 r = unit_full_printf(u, f, &path);
6
+                 if (r < 0) {
7
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", f);
8
+-                        return 0;
9
++                        log_syntax(unit, LOG_ERR, filename, line, r,
10
++                                   "Failed to resolve unit specifiers on %s%s: %m",
11
++                                   f, ignore ? ", ignoring" : "");
12
++                        return ignore ? 0 : -ENOEXEC;
13
+                 }
14
+ 
15
+                 if (isempty(path)) {
16
+                         /* First word is either "-" or "@" with no command. */
17
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue);
18
+-                        return 0;
19
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
20
++                                   "Empty path in command line%s: \"%s\"",
21
++                                   ignore ? ", ignoring" : "", rvalue);
22
++                        return ignore ? 0 : -ENOEXEC;
23
+                 }
24
+                 if (!string_is_safe(path)) {
25
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue);
26
+-                        return 0;
27
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
28
++                                   "Executable path contains special characters%s: %s",
29
++                                   ignore ? ", ignoring" : "", rvalue);
30
++                        return ignore ? 0 : -ENOEXEC;
31
+                 }
32
+                 if (!path_is_absolute(path)) {
33
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue);
34
+-                        return 0;
35
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
36
++                                   "Executable path is not absolute%s: %s",
37
++                                   ignore ? ", ignoring" : "", rvalue);
38
++                        return ignore ? 0 : -ENOEXEC;
39
+                 }
40
+                 if (endswith(path, "/")) {
41
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue);
42
+-                        return 0;
43
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
44
++                                   "Executable path specifies a directory%s: %s",
45
++                                   ignore ? ", ignoring" : "", rvalue);
46
++                        return ignore ? 0 : -ENOEXEC;
47
+                 }
48
+ 
49
+                 if (!separate_argv0) {
50
+@@ -708,12 +718,14 @@ int config_parse_exec(
51
+                         if (r == 0)
52
+                                 break;
53
+                         if (r < 0)
54
+-                                return 0;
55
++                                return ignore ? 0 : -ENOEXEC;
56
+ 
57
+                         r = unit_full_printf(u, word, &resolved);
58
+                         if (r < 0) {
59
+-                                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to resolve unit specifiers on %s, ignoring: %m", word);
60
+-                                return 0;
61
++                                log_syntax(unit, LOG_ERR, filename, line, r,
62
++                                           "Failed to resolve unit specifiers on %s%s: %m",
63
++                                           word, ignore ? ", ignoring" : "");
64
++                                return ignore ? 0 : -ENOEXEC;
65
+                         }
66
+ 
67
+                         if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
68
+@@ -724,8 +736,10 @@ int config_parse_exec(
69
+                 }
70
+ 
71
+                 if (!n || !n[0]) {
72
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Empty executable name or zeroeth argument, ignoring: %s", rvalue);
73
+-                        return 0;
74
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
75
++                                   "Empty executable name or zeroeth argument%s: %s",
76
++                                   ignore ? ", ignoring" : "", rvalue);
77
++                        return ignore ? 0 : -ENOEXEC;
78
+                 }
79
+ 
80
+                 nce = new0(ExecCommand, 1);
81
+@@ -1332,8 +1346,10 @@ int config_parse_exec_selinux_context(
82
+ 
83
+         r = unit_full_printf(u, rvalue, &k);
84
+         if (r < 0) {
85
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
86
+-                return 0;
87
++                log_syntax(unit, LOG_ERR, filename, line, r,
88
++                           "Failed to resolve specifiers%s: %m",
89
++                           ignore ? ", ignoring" : "");
90
++                return ignore ? 0 : -ENOEXEC;
91
+         }
92
+ 
93
+         free(c->selinux_context);
94
+@@ -1380,8 +1396,10 @@ int config_parse_exec_apparmor_profile(
95
+ 
96
+         r = unit_full_printf(u, rvalue, &k);
97
+         if (r < 0) {
98
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
99
+-                return 0;
100
++                log_syntax(unit, LOG_ERR, filename, line, r,
101
++                           "Failed to resolve specifiers%s: %m",
102
++                           ignore ? ", ignoring" : "");
103
++                return ignore ? 0 : -ENOEXEC;
104
+         }
105
+ 
106
+         free(c->apparmor_profile);
107
+@@ -1428,8 +1446,10 @@ int config_parse_exec_smack_process_label(
108
+ 
109
+         r = unit_full_printf(u, rvalue, &k);
110
+         if (r < 0) {
111
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
112
+-                return 0;
113
++                log_syntax(unit, LOG_ERR, filename, line, r,
114
++                           "Failed to resolve specifiers%s: %m",
115
++                           ignore ? ", ignoring" : "");
116
++                return ignore ? 0 : -ENOEXEC;
117
+         }
118
+ 
119
+         free(c->smack_process_label);
120
+@@ -1647,19 +1667,19 @@ int config_parse_socket_service(
121
+ 
122
+         r = unit_name_printf(UNIT(s), rvalue, &p);
123
+         if (r < 0) {
124
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
125
+-                return 0;
126
++                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", rvalue);
127
++                return -ENOEXEC;
128
+         }
129
+ 
130
+         if (!endswith(p, ".service")) {
131
+-                log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue);
132
+-                return 0;
133
++                log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue);
134
++                return -ENOEXEC;
135
+         }
136
+ 
137
+         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
138
+         if (r < 0) {
139
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
140
+-                return 0;
141
++                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r));
142
++                return -ENOEXEC;
143
+         }
144
+ 
145
+         unit_ref_set(&s->service, x);
146
+@@ -1907,13 +1927,13 @@ int config_parse_user_group(
147
+ 
148
+                 r = unit_full_printf(u, rvalue, &k);
149
+                 if (r < 0) {
150
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
151
+-                        return 0;
152
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue);
153
++                        return -ENOEXEC;
154
+                 }
155
+ 
156
+                 if (!valid_user_group_name_or_id(k)) {
157
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k);
158
+-                        return 0;
159
++                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
160
++                        return -ENOEXEC;
161
+                 }
162
+ 
163
+                 n = k;
164
+@@ -1971,19 +1991,19 @@ int config_parse_user_group_strv(
165
+                 if (r == -ENOMEM)
166
+                         return log_oom();
167
+                 if (r < 0) {
168
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
169
+-                        break;
170
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue);
171
++                        return -ENOEXEC;
172
+                 }
173
+ 
174
+                 r = unit_full_printf(u, word, &k);
175
+                 if (r < 0) {
176
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word);
177
+-                        continue;
178
++                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", word);
179
++                        return -ENOEXEC;
180
+                 }
181
+ 
182
+                 if (!valid_user_group_name_or_id(k)) {
183
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k);
184
+-                        continue;
185
++                        log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k);
186
++                        return -ENOEXEC;
187
+                 }
188
+ 
189
+                 r = strv_push(users, k);
190
+@@ -2142,25 +2162,28 @@ int config_parse_working_directory(
191
+ 
192
+                 r = unit_full_printf(u, rvalue, &k);
193
+                 if (r < 0) {
194
+-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue);
195
+-                        return 0;
196
++                        log_syntax(unit, LOG_ERR, filename, line, r,
197
++                                   "Failed to resolve unit specifiers in working directory path '%s'%s: %m",
198
++                                   rvalue, missing_ok ? ", ignoring" : "");
199
++                        return missing_ok ? 0 : -ENOEXEC;
200
+                 }
201
+ 
202
+                 path_kill_slashes(k);
203
+ 
204
+                 if (!utf8_is_valid(k)) {
205
+                         log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
206
+-                        return 0;
207
++                        return missing_ok ? 0 : -ENOEXEC;
208
+                 }
209
+ 
210
+                 if (!path_is_absolute(k)) {
211
+-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue);
212
+-                        return 0;
213
++                        log_syntax(unit, LOG_ERR, filename, line, 0,
214
++                                   "Working directory path '%s' is not absolute%s.",
215
++                                   rvalue, missing_ok ? ", ignoring" : "");
216
++                        return missing_ok ? 0 : -ENOEXEC;
217
+                 }
218
+ 
219
+-                free_and_replace(c->working_directory, k);
220
+-
221
+                 c->working_directory_home = false;
222
++                free_and_replace(c->working_directory, k);
223
+         }
224
+ 
225
+         c->working_directory_missing_ok = missing_ok;
226
+@@ -4456,8 +4479,11 @@ int unit_load_fragment(Unit *u) {
227
+                         return r;
228
+ 
229
+                 r = load_from_path(u, k);
230
+-                if (r < 0)
231
++                if (r < 0) {
232
++                        if (r == -ENOEXEC)
233
++                                log_unit_notice(u, "Unit configuration has fatal error, unit will not be started.");
234
+                         return r;
235
++                }
236
+ 
237
+                 if (u->load_state == UNIT_STUB) {
238
+                         SET_FOREACH(t, u->names, i) {
239
+diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
240
+index 12f48bf435..fd797b587e 100644
241
+--- a/src/test/test-unit-file.c
242
+@@ -146,7 +146,7 @@ static void test_config_parse_exec(void) {
243
+         r = config_parse_exec(NULL, "fake", 4, "section", 1,
244
+                               "LValue", 0, "/RValue/ argv0 r1",
245
+                               &c, u);
246
+-        assert_se(r == 0);
247
++        assert_se(r == -ENOEXEC);
248
+         assert_se(c1->command_next == NULL);
249
+ 
250
+         log_info("/* honour_argv0 */");
251
+@@ -161,7 +161,7 @@ static void test_config_parse_exec(void) {
252
+         r = config_parse_exec(NULL, "fake", 3, "section", 1,
253
+                               "LValue", 0, "@/RValue",
254
+                               &c, u);
255
+-        assert_se(r == 0);
256
++        assert_se(r == -ENOEXEC);
257
+         assert_se(c1->command_next == NULL);
258
+ 
259
+         log_info("/* no command, whitespace only, reset */");
260
+@@ -220,7 +220,7 @@ static void test_config_parse_exec(void) {
261
+                               "-@/RValue argv0 r1 ; ; "
262
+                               "/goo/goo boo",
263
+                               &c, u);
264
+-        assert_se(r >= 0);
265
++        assert_se(r == -ENOEXEC);
266
+         c1 = c1->command_next;
267
+         check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true);
268
+ 
269
+@@ -374,7 +374,7 @@ static void test_config_parse_exec(void) {
270
+                 r = config_parse_exec(NULL, "fake", 4, "section", 1,
271
+                                       "LValue", 0, path,
272
+                                       &c, u);
273
+-                assert_se(r == 0);
274
++                assert_se(r == -ENOEXEC);
275
+                 assert_se(c1->command_next == NULL);
276
+         }
277
+ 
278
+@@ -401,21 +401,21 @@ static void test_config_parse_exec(void) {
279
+         r = config_parse_exec(NULL, "fake", 4, "section", 1,
280
+                               "LValue", 0, "/path\\",
281
+                               &c, u);
282
+-        assert_se(r == 0);
283
++        assert_se(r == -ENOEXEC);
284
+         assert_se(c1->command_next == NULL);
285
+ 
286
+         log_info("/* missing ending ' */");
287
+         r = config_parse_exec(NULL, "fake", 4, "section", 1,
288
+                               "LValue", 0, "/path 'foo",
289
+                               &c, u);
290
+-        assert_se(r == 0);
291
++        assert_se(r == -ENOEXEC);
292
+         assert_se(c1->command_next == NULL);
293
+ 
294
+         log_info("/* missing ending ' with trailing backslash */");
295
+         r = config_parse_exec(NULL, "fake", 4, "section", 1,
296
+                               "LValue", 0, "/path 'foo\\",
297
+                               &c, u);
298
+-        assert_se(r == 0);
299
++        assert_se(r == -ENOEXEC);
300
+         assert_se(c1->command_next == NULL);
301
+ 
302
+         log_info("/* invalid space between modifiers */");
0 303
new file mode 100644
... ...
@@ -0,0 +1,100 @@
0
+diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
1
+index c43b7885be..5b5a86250e 100644
2
+--- a/src/core/load-fragment-gperf.gperf.m4
3
+@@ -18,8 +18,8 @@ struct ConfigPerfItem;
4
+ m4_dnl Define the context options only once
5
+ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
6
+ `$1.WorkingDirectory,            config_parse_working_directory,     0,                             offsetof($1, exec_context)
7
+-$1.RootDirectory,                config_parse_unit_path_printf,      0,                             offsetof($1, exec_context.root_directory)
8
+-$1.RootImage,                    config_parse_unit_path_printf,      0,                             offsetof($1, exec_context.root_image)
9
++$1.RootDirectory,                config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_directory)
10
++$1.RootImage,                    config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_image)
11
+ $1.User,                         config_parse_user_group,            0,                             offsetof($1, exec_context.user)
12
+ $1.Group,                        config_parse_user_group,            0,                             offsetof($1, exec_context.group)
13
+ $1.SupplementaryGroups,          config_parse_user_group_strv,       0,                             offsetof($1, exec_context.supplementary_groups)
14
+@@ -35,7 +35,7 @@ $1.UMask,                        config_parse_mode,                  0,
15
+ $1.Environment,                  config_parse_environ,               0,                             offsetof($1, exec_context.environment)
16
+ $1.EnvironmentFile,              config_parse_unit_env_file,         0,                             offsetof($1, exec_context.environment_files)
17
+ $1.PassEnvironment,              config_parse_pass_environ,          0,                             offsetof($1, exec_context.pass_environment)
18
+-$1.DynamicUser,                  config_parse_bool,                  0,                             offsetof($1, exec_context.dynamic_user)
19
++$1.DynamicUser,                  config_parse_bool,                  true,                          offsetof($1, exec_context.dynamic_user)
20
+ $1.StandardInput,                config_parse_exec_input,            0,                             offsetof($1, exec_context)
21
+ $1.StandardOutput,               config_parse_exec_output,           0,                             offsetof($1, exec_context)
22
+ $1.StandardError,                config_parse_exec_output,           0,                             offsetof($1, exec_context)
23
+diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
24
+index 49a5c53f96..9d5c39b3dd 100644
25
+--- a/src/core/load-fragment.c
26
+@@ -242,6 +242,7 @@ int config_parse_unit_path_printf(
27
+         _cleanup_free_ char *k = NULL;
28
+         Unit *u = userdata;
29
+         int r;
30
++        bool fatal = ltype;
31
+ 
32
+         assert(filename);
33
+         assert(lvalue);
34
+@@ -250,8 +251,10 @@ int config_parse_unit_path_printf(
35
+ 
36
+         r = unit_full_printf(u, rvalue, &k);
37
+         if (r < 0) {
38
+-                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
39
+-                return 0;
40
++                log_syntax(unit, LOG_ERR, filename, line, r,
41
++                           "Failed to resolve unit specifiers on %s%s: %m",
42
++                           fatal ? "" : ", ignoring", rvalue);
43
++                return fatal ? -ENOEXEC : 0;
44
+         }
45
+ 
46
+         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
47
+diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
48
+index 44df7493e2..e08402e3d2 100644
49
+--- a/src/shared/conf-parser.c
50
+@@ -615,6 +615,7 @@ int config_parse_bool(const char* unit,
51
+ 
52
+         int k;
53
+         bool *b = data;
54
++        bool fatal = ltype;
55
+ 
56
+         assert(filename);
57
+         assert(lvalue);
58
+@@ -623,8 +624,10 @@ int config_parse_bool(const char* unit,
59
+ 
60
+         k = parse_boolean(rvalue);
61
+         if (k < 0) {
62
+-                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse boolean value, ignoring: %s", rvalue);
63
+-                return 0;
64
++                log_syntax(unit, LOG_ERR, filename, line, k,
65
++                           "Failed to parse boolean value%s: %s",
66
++                           fatal ? "" : ", ignoring", rvalue);
67
++                return fatal ? -ENOEXEC : 0;
68
+         }
69
+ 
70
+         *b = !!k;
71
+@@ -715,6 +718,7 @@ int config_parse_path(
72
+                 void *userdata) {
73
+ 
74
+         char **s = data, *n;
75
++        bool fatal = ltype;
76
+ 
77
+         assert(filename);
78
+         assert(lvalue);
79
+@@ -723,12 +727,14 @@ int config_parse_path(
80
+ 
81
+         if (!utf8_is_valid(rvalue)) {
82
+                 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
83
+-                return 0;
84
++                return fatal ? -ENOEXEC : 0;
85
+         }
86
+ 
87
+         if (!path_is_absolute(rvalue)) {
88
+-                log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", rvalue);
89
+-                return 0;
90
++                log_syntax(unit, LOG_ERR, filename, line, 0,
91
++                           "Not an absolute path%s: %s",
92
++                           fatal ? "" : ", ignoring", rvalue);
93
++                return fatal ? -ENOEXEC : 0;
94
+         }
95
+ 
96
+         n = strdup(rvalue);
... ...
@@ -1,7 +1,7 @@
1 1
 Summary:          Systemd-233
2 2
 Name:             systemd
3 3
 Version:          233
4
-Release:          5%{?dist}
4
+Release:          6%{?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
... ...
@@ -22,6 +22,8 @@ Patch5:           systemd-macros.patch
22 22
 Patch6:           systemd-233-resolv-conf-symlink.patch
23 23
 Patch7:           systemd-233-CVE-2017-9217.patch
24 24
 Patch8:           systemd-233-CVE-2017-9445-dns-oob.patch
25
+Patch9:           systemd-233-CVE-2017-1000082-1.patch
26
+Patch10:          systemd-233-CVE-2017-1000082-2.patch
25 27
 
26 28
 Requires:         Linux-PAM
27 29
 Requires:         libcap
... ...
@@ -79,6 +81,8 @@ sed -i "s:blkid/::" $(grep -rl "blkid/blkid.h")
79 79
 %patch6 -p1
80 80
 %patch7 -p1
81 81
 %patch8 -p1
82
+%patch9 -p1
83
+%patch10 -p1
82 84
 
83 85
 sed -i "s#\#DefaultTasksMax=512#DefaultTasksMax=infinity#g" src/core/system.conf
84 86
 
... ...
@@ -226,6 +230,8 @@ rm -rf %{buildroot}/*
226 226
 %files lang -f %{name}.lang
227 227
 
228 228
 %changelog
229
+*    Fri Jul 20 2017 Vinay Kulkarni <kulkarniv@vmware.com>  233-6
230
+-    Fix for CVE-2017-1000082.
229 231
 *    Fri Jul 07 2017 Vinay Kulkarni <kulkarniv@vmware.com>  233-5
230 232
 -    Fix default-dns-from-env patch.
231 233
 *    Wed Jul 05 2017 Xiaolin Li <xiaolinl@vmware.com> 233-4