diff options
| author | Ross Burton <ross.burton@intel.com> | 2017-08-04 17:27:00 +0100 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-08-29 16:50:54 +0100 |
| commit | 07e5111828d6cad3133beb23e50312e4a5d6b73c (patch) | |
| tree | 9fddc30e54563a135f770c98657b6385e9ddc4c1 /meta/recipes-core | |
| parent | 7cc37c53909d958fd432f93c8f569a4de69a298f (diff) | |
| download | poky-07e5111828d6cad3133beb23e50312e4a5d6b73c.tar.gz | |
systemd: refuse to load units with errors (CVE-2017-1000082)
If a unit has a statement such as User=0day where the username exists but is
strictly speaking invalid, the unit will be started as the root user instead.
Backport a patch from upstream to mitigate this by refusing to start units such
as this.
(From OE-Core rev: e56cb926c170f493ee2a9c4c63d0ecbf883d4685)
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-core')
| -rw-r--r-- | meta/recipes-core/systemd/systemd/validate-user.patch | 856 | ||||
| -rw-r--r-- | meta/recipes-core/systemd/systemd_230.bb | 1 |
2 files changed, 857 insertions, 0 deletions
diff --git a/meta/recipes-core/systemd/systemd/validate-user.patch b/meta/recipes-core/systemd/systemd/validate-user.patch new file mode 100644 index 0000000000..8e0e0c1b9a --- /dev/null +++ b/meta/recipes-core/systemd/systemd/validate-user.patch | |||
| @@ -0,0 +1,856 @@ | |||
| 1 | If a user is created with a strictly-speaking invalid name such as '0day' and a | ||
| 2 | unit created to run as that user, systemd rejects the username and runs the unit | ||
| 3 | as root. | ||
| 4 | |||
| 5 | CVE: CVE-2017-1000082 | ||
| 6 | Upstream-Status: Backport | ||
| 7 | Signed-off-by: Ross Burton <ross.burton@intel.com> | ||
| 8 | |||
| 9 | From e0c4eb1435d50cb3797cf94100d4886dc2022bce Mon Sep 17 00:00:00 2001 | ||
| 10 | From: Lennart Poettering <lennart@poettering.net> | ||
| 11 | Date: Thu, 14 Jul 2016 12:23:39 +0200 | ||
| 12 | Subject: [PATCH 1/3] sysusers: move various user credential validity checks to | ||
| 13 | src/basic/ | ||
| 14 | |||
| 15 | This way we can reuse them for validating User=/Group= settings in unit files | ||
| 16 | (to be added in a later commit). | ||
| 17 | |||
| 18 | Also, add some tests for them. | ||
| 19 | --- | ||
| 20 | src/basic/user-util.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ | ||
| 21 | src/basic/user-util.h | 5 +++ | ||
| 22 | src/sysusers/sysusers.c | 75 -------------------------------------- | ||
| 23 | src/test/test-user-util.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ | ||
| 24 | 4 files changed, 185 insertions(+), 75 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/src/basic/user-util.c b/src/basic/user-util.c | ||
| 27 | index f65ca3eda..c85b5c6a8 100644 | ||
| 28 | --- a/src/basic/user-util.c | ||
| 29 | +++ b/src/basic/user-util.c | ||
| 30 | @@ -29,6 +29,7 @@ | ||
| 31 | #include <string.h> | ||
| 32 | #include <sys/stat.h> | ||
| 33 | #include <unistd.h> | ||
| 34 | +#include <utmp.h> | ||
| 35 | |||
| 36 | #include "missing.h" | ||
| 37 | #include "alloc-util.h" | ||
| 38 | @@ -39,6 +40,7 @@ | ||
| 39 | #include "path-util.h" | ||
| 40 | #include "string-util.h" | ||
| 41 | #include "user-util.h" | ||
| 42 | +#include "utf8.h" | ||
| 43 | |||
| 44 | bool uid_is_valid(uid_t uid) { | ||
| 45 | |||
| 46 | @@ -479,3 +481,94 @@ int take_etc_passwd_lock(const char *root) { | ||
| 47 | |||
| 48 | return fd; | ||
| 49 | } | ||
| 50 | + | ||
| 51 | +bool valid_user_group_name(const char *u) { | ||
| 52 | + const char *i; | ||
| 53 | + long sz; | ||
| 54 | + | ||
| 55 | + /* Checks if the specified name is a valid user/group name. */ | ||
| 56 | + | ||
| 57 | + if (isempty(u)) | ||
| 58 | + return false; | ||
| 59 | + | ||
| 60 | + if (!(u[0] >= 'a' && u[0] <= 'z') && | ||
| 61 | + !(u[0] >= 'A' && u[0] <= 'Z') && | ||
| 62 | + u[0] != '_') | ||
| 63 | + return false; | ||
| 64 | + | ||
| 65 | + for (i = u+1; *i; i++) { | ||
| 66 | + if (!(*i >= 'a' && *i <= 'z') && | ||
| 67 | + !(*i >= 'A' && *i <= 'Z') && | ||
| 68 | + !(*i >= '0' && *i <= '9') && | ||
| 69 | + *i != '_' && | ||
| 70 | + *i != '-') | ||
| 71 | + return false; | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + sz = sysconf(_SC_LOGIN_NAME_MAX); | ||
| 75 | + assert_se(sz > 0); | ||
| 76 | + | ||
| 77 | + if ((size_t) (i-u) > (size_t) sz) | ||
| 78 | + return false; | ||
| 79 | + | ||
| 80 | + if ((size_t) (i-u) > UT_NAMESIZE - 1) | ||
| 81 | + return false; | ||
| 82 | + | ||
| 83 | + return true; | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +bool valid_user_group_name_or_id(const char *u) { | ||
| 87 | + | ||
| 88 | + /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the right | ||
| 89 | + * range, and not the invalid user ids. */ | ||
| 90 | + | ||
| 91 | + if (isempty(u)) | ||
| 92 | + return false; | ||
| 93 | + | ||
| 94 | + if (valid_user_group_name(u)) | ||
| 95 | + return true; | ||
| 96 | + | ||
| 97 | + return parse_uid(u, NULL) >= 0; | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +bool valid_gecos(const char *d) { | ||
| 101 | + | ||
| 102 | + if (!d) | ||
| 103 | + return false; | ||
| 104 | + | ||
| 105 | + if (!utf8_is_valid(d)) | ||
| 106 | + return false; | ||
| 107 | + | ||
| 108 | + if (string_has_cc(d, NULL)) | ||
| 109 | + return false; | ||
| 110 | + | ||
| 111 | + /* Colons are used as field separators, and hence not OK */ | ||
| 112 | + if (strchr(d, ':')) | ||
| 113 | + return false; | ||
| 114 | + | ||
| 115 | + return true; | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +bool valid_home(const char *p) { | ||
| 119 | + | ||
| 120 | + if (isempty(p)) | ||
| 121 | + return false; | ||
| 122 | + | ||
| 123 | + if (!utf8_is_valid(p)) | ||
| 124 | + return false; | ||
| 125 | + | ||
| 126 | + if (string_has_cc(p, NULL)) | ||
| 127 | + return false; | ||
| 128 | + | ||
| 129 | + if (!path_is_absolute(p)) | ||
| 130 | + return false; | ||
| 131 | + | ||
| 132 | + if (!path_is_safe(p)) | ||
| 133 | + return false; | ||
| 134 | + | ||
| 135 | + /* Colons are used as field separators, and hence not OK */ | ||
| 136 | + if (strchr(p, ':')) | ||
| 137 | + return false; | ||
| 138 | + | ||
| 139 | + return true; | ||
| 140 | +} | ||
| 141 | diff --git a/src/basic/user-util.h b/src/basic/user-util.h | ||
| 142 | index 8026eca3f..36f71fb00 100644 | ||
| 143 | --- a/src/basic/user-util.h | ||
| 144 | +++ b/src/basic/user-util.h | ||
| 145 | @@ -68,3 +68,8 @@ int take_etc_passwd_lock(const char *root); | ||
| 146 | static inline bool userns_supported(void) { | ||
| 147 | return access("/proc/self/uid_map", F_OK) >= 0; | ||
| 148 | } | ||
| 149 | + | ||
| 150 | +bool valid_user_group_name(const char *u); | ||
| 151 | +bool valid_user_group_name_or_id(const char *u); | ||
| 152 | +bool valid_gecos(const char *d); | ||
| 153 | +bool valid_home(const char *p); | ||
| 154 | diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c | ||
| 155 | index 4377f1b91..df3b7de30 100644 | ||
| 156 | --- a/src/sysusers/sysusers.c | ||
| 157 | +++ b/src/sysusers/sysusers.c | ||
| 158 | @@ -1299,81 +1299,6 @@ static bool item_equal(Item *a, Item *b) { | ||
| 159 | return true; | ||
| 160 | } | ||
| 161 | |||
| 162 | -static bool valid_user_group_name(const char *u) { | ||
| 163 | - const char *i; | ||
| 164 | - long sz; | ||
| 165 | - | ||
| 166 | - if (isempty(u)) | ||
| 167 | - return false; | ||
| 168 | - | ||
| 169 | - if (!(u[0] >= 'a' && u[0] <= 'z') && | ||
| 170 | - !(u[0] >= 'A' && u[0] <= 'Z') && | ||
| 171 | - u[0] != '_') | ||
| 172 | - return false; | ||
| 173 | - | ||
| 174 | - for (i = u+1; *i; i++) { | ||
| 175 | - if (!(*i >= 'a' && *i <= 'z') && | ||
| 176 | - !(*i >= 'A' && *i <= 'Z') && | ||
| 177 | - !(*i >= '0' && *i <= '9') && | ||
| 178 | - *i != '_' && | ||
| 179 | - *i != '-') | ||
| 180 | - return false; | ||
| 181 | - } | ||
| 182 | - | ||
| 183 | - sz = sysconf(_SC_LOGIN_NAME_MAX); | ||
| 184 | - assert_se(sz > 0); | ||
| 185 | - | ||
| 186 | - if ((size_t) (i-u) > (size_t) sz) | ||
| 187 | - return false; | ||
| 188 | - | ||
| 189 | - if ((size_t) (i-u) > UT_NAMESIZE - 1) | ||
| 190 | - return false; | ||
| 191 | - | ||
| 192 | - return true; | ||
| 193 | -} | ||
| 194 | - | ||
| 195 | -static bool valid_gecos(const char *d) { | ||
| 196 | - | ||
| 197 | - if (!d) | ||
| 198 | - return false; | ||
| 199 | - | ||
| 200 | - if (!utf8_is_valid(d)) | ||
| 201 | - return false; | ||
| 202 | - | ||
| 203 | - if (string_has_cc(d, NULL)) | ||
| 204 | - return false; | ||
| 205 | - | ||
| 206 | - /* Colons are used as field separators, and hence not OK */ | ||
| 207 | - if (strchr(d, ':')) | ||
| 208 | - return false; | ||
| 209 | - | ||
| 210 | - return true; | ||
| 211 | -} | ||
| 212 | - | ||
| 213 | -static bool valid_home(const char *p) { | ||
| 214 | - | ||
| 215 | - if (isempty(p)) | ||
| 216 | - return false; | ||
| 217 | - | ||
| 218 | - if (!utf8_is_valid(p)) | ||
| 219 | - return false; | ||
| 220 | - | ||
| 221 | - if (string_has_cc(p, NULL)) | ||
| 222 | - return false; | ||
| 223 | - | ||
| 224 | - if (!path_is_absolute(p)) | ||
| 225 | - return false; | ||
| 226 | - | ||
| 227 | - if (!path_is_safe(p)) | ||
| 228 | - return false; | ||
| 229 | - | ||
| 230 | - /* Colons are used as field separators, and hence not OK */ | ||
| 231 | - if (strchr(p, ':')) | ||
| 232 | - return false; | ||
| 233 | - | ||
| 234 | - return true; | ||
| 235 | -} | ||
| 236 | - | ||
| 237 | static int parse_line(const char *fname, unsigned line, const char *buffer) { | ||
| 238 | |||
| 239 | static const Specifier specifier_table[] = { | ||
| 240 | diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c | ||
| 241 | index 8d1ec19f1..2a344a9f9 100644 | ||
| 242 | --- a/src/test/test-user-util.c | ||
| 243 | +++ b/src/test/test-user-util.c | ||
| 244 | @@ -61,6 +61,88 @@ static void test_uid_ptr(void) { | ||
| 245 | assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000); | ||
| 246 | } | ||
| 247 | |||
| 248 | +static void test_valid_user_group_name(void) { | ||
| 249 | + assert_se(!valid_user_group_name(NULL)); | ||
| 250 | + assert_se(!valid_user_group_name("")); | ||
| 251 | + assert_se(!valid_user_group_name("1")); | ||
| 252 | + assert_se(!valid_user_group_name("65535")); | ||
| 253 | + assert_se(!valid_user_group_name("-1")); | ||
| 254 | + assert_se(!valid_user_group_name("-kkk")); | ||
| 255 | + assert_se(!valid_user_group_name("rööt")); | ||
| 256 | + assert_se(!valid_user_group_name(".")); | ||
| 257 | + assert_se(!valid_user_group_name("eff.eff")); | ||
| 258 | + assert_se(!valid_user_group_name("foo\nbar")); | ||
| 259 | + assert_se(!valid_user_group_name("0123456789012345678901234567890123456789")); | ||
| 260 | + assert_se(!valid_user_group_name_or_id("aaa:bbb")); | ||
| 261 | + | ||
| 262 | + assert_se(valid_user_group_name("root")); | ||
| 263 | + assert_se(valid_user_group_name("lennart")); | ||
| 264 | + assert_se(valid_user_group_name("LENNART")); | ||
| 265 | + assert_se(valid_user_group_name("_kkk")); | ||
| 266 | + assert_se(valid_user_group_name("kkk-")); | ||
| 267 | + assert_se(valid_user_group_name("kk-k")); | ||
| 268 | + | ||
| 269 | + assert_se(valid_user_group_name("some5")); | ||
| 270 | + assert_se(!valid_user_group_name("5some")); | ||
| 271 | + assert_se(valid_user_group_name("INNER5NUMBER")); | ||
| 272 | +} | ||
| 273 | + | ||
| 274 | +static void test_valid_user_group_name_or_id(void) { | ||
| 275 | + assert_se(!valid_user_group_name_or_id(NULL)); | ||
| 276 | + assert_se(!valid_user_group_name_or_id("")); | ||
| 277 | + assert_se(valid_user_group_name_or_id("0")); | ||
| 278 | + assert_se(valid_user_group_name_or_id("1")); | ||
| 279 | + assert_se(valid_user_group_name_or_id("65534")); | ||
| 280 | + assert_se(!valid_user_group_name_or_id("65535")); | ||
| 281 | + assert_se(valid_user_group_name_or_id("65536")); | ||
| 282 | + assert_se(!valid_user_group_name_or_id("-1")); | ||
| 283 | + assert_se(!valid_user_group_name_or_id("-kkk")); | ||
| 284 | + assert_se(!valid_user_group_name_or_id("rööt")); | ||
| 285 | + assert_se(!valid_user_group_name_or_id(".")); | ||
| 286 | + assert_se(!valid_user_group_name_or_id("eff.eff")); | ||
| 287 | + assert_se(!valid_user_group_name_or_id("foo\nbar")); | ||
| 288 | + assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789")); | ||
| 289 | + assert_se(!valid_user_group_name_or_id("aaa:bbb")); | ||
| 290 | + | ||
| 291 | + assert_se(valid_user_group_name_or_id("root")); | ||
| 292 | + assert_se(valid_user_group_name_or_id("lennart")); | ||
| 293 | + assert_se(valid_user_group_name_or_id("LENNART")); | ||
| 294 | + assert_se(valid_user_group_name_or_id("_kkk")); | ||
| 295 | + assert_se(valid_user_group_name_or_id("kkk-")); | ||
| 296 | + assert_se(valid_user_group_name_or_id("kk-k")); | ||
| 297 | + | ||
| 298 | + assert_se(valid_user_group_name_or_id("some5")); | ||
| 299 | + assert_se(!valid_user_group_name_or_id("5some")); | ||
| 300 | + assert_se(valid_user_group_name_or_id("INNER5NUMBER")); | ||
| 301 | +} | ||
| 302 | + | ||
| 303 | +static void test_valid_gecos(void) { | ||
| 304 | + | ||
| 305 | + assert_se(!valid_gecos(NULL)); | ||
| 306 | + assert_se(valid_gecos("")); | ||
| 307 | + assert_se(valid_gecos("test")); | ||
| 308 | + assert_se(valid_gecos("Ümläüt")); | ||
| 309 | + assert_se(!valid_gecos("In\nvalid")); | ||
| 310 | + assert_se(!valid_gecos("In:valid")); | ||
| 311 | +} | ||
| 312 | + | ||
| 313 | +static void test_valid_home(void) { | ||
| 314 | + | ||
| 315 | + assert_se(!valid_home(NULL)); | ||
| 316 | + assert_se(!valid_home("")); | ||
| 317 | + assert_se(!valid_home(".")); | ||
| 318 | + assert_se(!valid_home("/home/..")); | ||
| 319 | + assert_se(!valid_home("/home/../")); | ||
| 320 | + assert_se(!valid_home("/home\n/foo")); | ||
| 321 | + assert_se(!valid_home("./piep")); | ||
| 322 | + assert_se(!valid_home("piep")); | ||
| 323 | + assert_se(!valid_home("/home/user:lennart")); | ||
| 324 | + | ||
| 325 | + assert_se(valid_home("/")); | ||
| 326 | + assert_se(valid_home("/home")); | ||
| 327 | + assert_se(valid_home("/home/foo")); | ||
| 328 | +} | ||
| 329 | + | ||
| 330 | int main(int argc, char*argv[]) { | ||
| 331 | |||
| 332 | test_uid_to_name_one(0, "root"); | ||
| 333 | @@ -75,5 +157,10 @@ int main(int argc, char*argv[]) { | ||
| 334 | test_parse_uid(); | ||
| 335 | test_uid_ptr(); | ||
| 336 | |||
| 337 | + test_valid_user_group_name(); | ||
| 338 | + test_valid_user_group_name_or_id(); | ||
| 339 | + test_valid_gecos(); | ||
| 340 | + test_valid_home(); | ||
| 341 | + | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | -- | ||
| 345 | 2.11.0 | ||
| 346 | |||
| 347 | |||
| 348 | From 1affacaaf6eff93e53563a644567cc5c3930cb28 Mon Sep 17 00:00:00 2001 | ||
| 349 | From: Lennart Poettering <lennart@poettering.net> | ||
| 350 | Date: Thu, 14 Jul 2016 12:28:06 +0200 | ||
| 351 | Subject: [PATCH 2/3] core: be stricter when parsing User=/Group= fields | ||
| 352 | |||
| 353 | Let's verify the validity of the syntax of the user/group names set. | ||
| 354 | --- | ||
| 355 | src/core/load-fragment-gperf.gperf.m4 | 10 +-- | ||
| 356 | src/core/load-fragment.c | 118 ++++++++++++++++++++++++++++++++++ | ||
| 357 | src/core/load-fragment.h | 2 + | ||
| 358 | 3 files changed, 125 insertions(+), 5 deletions(-) | ||
| 359 | |||
| 360 | diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 | ||
| 361 | index 819341898..110089696 100644 | ||
| 362 | --- a/src/core/load-fragment-gperf.gperf.m4 | ||
| 363 | +++ b/src/core/load-fragment-gperf.gperf.m4 | ||
| 364 | @@ -19,9 +19,9 @@ m4_dnl Define the context options only once | ||
| 365 | m4_define(`EXEC_CONTEXT_CONFIG_ITEMS', | ||
| 366 | `$1.WorkingDirectory, config_parse_working_directory, 0, offsetof($1, exec_context) | ||
| 367 | $1.RootDirectory, config_parse_unit_path_printf, 0, offsetof($1, exec_context.root_directory) | ||
| 368 | -$1.User, config_parse_unit_string_printf, 0, offsetof($1, exec_context.user) | ||
| 369 | -$1.Group, config_parse_unit_string_printf, 0, offsetof($1, exec_context.group) | ||
| 370 | -$1.SupplementaryGroups, config_parse_strv, 0, offsetof($1, exec_context.supplementary_groups) | ||
| 371 | +$1.User, config_parse_user_group, 0, offsetof($1, exec_context.user) | ||
| 372 | +$1.Group, config_parse_user_group, 0, offsetof($1, exec_context.group) | ||
| 373 | +$1.SupplementaryGroups, config_parse_user_group_strv, 0, offsetof($1, exec_context.supplementary_groups) | ||
| 374 | $1.Nice, config_parse_exec_nice, 0, offsetof($1, exec_context) | ||
| 375 | $1.OOMScoreAdjust, config_parse_exec_oom_score_adjust, 0, offsetof($1, exec_context) | ||
| 376 | $1.IOSchedulingClass, config_parse_exec_io_class, 0, offsetof($1, exec_context) | ||
| 377 | @@ -275,8 +275,8 @@ Socket.ExecStartPost, config_parse_exec, SOCKET_EXEC | ||
| 378 | Socket.ExecStopPre, config_parse_exec, SOCKET_EXEC_STOP_PRE, offsetof(Socket, exec_command) | ||
| 379 | Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC_STOP_POST, offsetof(Socket, exec_command) | ||
| 380 | Socket.TimeoutSec, config_parse_sec, 0, offsetof(Socket, timeout_usec) | ||
| 381 | -Socket.SocketUser, config_parse_unit_string_printf, 0, offsetof(Socket, user) | ||
| 382 | -Socket.SocketGroup, config_parse_unit_string_printf, 0, offsetof(Socket, group) | ||
| 383 | +Socket.SocketUser, config_parse_user_group, 0, offsetof(Socket, user) | ||
| 384 | +Socket.SocketGroup, config_parse_user_group, 0, offsetof(Socket, group) | ||
| 385 | Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode) | ||
| 386 | Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode) | ||
| 387 | Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept) | ||
| 388 | diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c | ||
| 389 | index 86b4fb071..f43781803 100644 | ||
| 390 | --- a/src/core/load-fragment.c | ||
| 391 | +++ b/src/core/load-fragment.c | ||
| 392 | @@ -64,6 +64,7 @@ | ||
| 393 | #include "unit-name.h" | ||
| 394 | #include "unit-printf.h" | ||
| 395 | #include "unit.h" | ||
| 396 | +#include "user-util.h" | ||
| 397 | #include "utf8.h" | ||
| 398 | #include "web-util.h" | ||
| 399 | |||
| 400 | @@ -1758,6 +1759,123 @@ int config_parse_sec_fix_0( | ||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | +int config_parse_user_group( | ||
| 405 | + const char *unit, | ||
| 406 | + const char *filename, | ||
| 407 | + unsigned line, | ||
| 408 | + const char *section, | ||
| 409 | + unsigned section_line, | ||
| 410 | + const char *lvalue, | ||
| 411 | + int ltype, | ||
| 412 | + const char *rvalue, | ||
| 413 | + void *data, | ||
| 414 | + void *userdata) { | ||
| 415 | + | ||
| 416 | + char **user = data, *n; | ||
| 417 | + Unit *u = userdata; | ||
| 418 | + int r; | ||
| 419 | + | ||
| 420 | + assert(filename); | ||
| 421 | + assert(lvalue); | ||
| 422 | + assert(rvalue); | ||
| 423 | + assert(u); | ||
| 424 | + | ||
| 425 | + if (isempty(rvalue)) | ||
| 426 | + n = NULL; | ||
| 427 | + else { | ||
| 428 | + _cleanup_free_ char *k = NULL; | ||
| 429 | + | ||
| 430 | + r = unit_full_printf(u, rvalue, &k); | ||
| 431 | + if (r < 0) { | ||
| 432 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); | ||
| 433 | + return 0; | ||
| 434 | + } | ||
| 435 | + | ||
| 436 | + if (!valid_user_group_name_or_id(k)) { | ||
| 437 | + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); | ||
| 438 | + return 0; | ||
| 439 | + } | ||
| 440 | + | ||
| 441 | + n = k; | ||
| 442 | + k = NULL; | ||
| 443 | + } | ||
| 444 | + | ||
| 445 | + free(*user); | ||
| 446 | + *user = n; | ||
| 447 | + | ||
| 448 | + return 0; | ||
| 449 | +} | ||
| 450 | + | ||
| 451 | +int config_parse_user_group_strv( | ||
| 452 | + const char *unit, | ||
| 453 | + const char *filename, | ||
| 454 | + unsigned line, | ||
| 455 | + const char *section, | ||
| 456 | + unsigned section_line, | ||
| 457 | + const char *lvalue, | ||
| 458 | + int ltype, | ||
| 459 | + const char *rvalue, | ||
| 460 | + void *data, | ||
| 461 | + void *userdata) { | ||
| 462 | + | ||
| 463 | + char ***users = data; | ||
| 464 | + Unit *u = userdata; | ||
| 465 | + const char *p; | ||
| 466 | + int r; | ||
| 467 | + | ||
| 468 | + assert(filename); | ||
| 469 | + assert(lvalue); | ||
| 470 | + assert(rvalue); | ||
| 471 | + assert(u); | ||
| 472 | + | ||
| 473 | + if (isempty(rvalue)) { | ||
| 474 | + char **empty; | ||
| 475 | + | ||
| 476 | + empty = new0(char*, 1); | ||
| 477 | + if (!empty) | ||
| 478 | + return log_oom(); | ||
| 479 | + | ||
| 480 | + strv_free(*users); | ||
| 481 | + *users = empty; | ||
| 482 | + | ||
| 483 | + return 0; | ||
| 484 | + } | ||
| 485 | + | ||
| 486 | + p = rvalue; | ||
| 487 | + for (;;) { | ||
| 488 | + _cleanup_free_ char *word = NULL, *k = NULL; | ||
| 489 | + | ||
| 490 | + r = extract_first_word(&p, &word, WHITESPACE, 0); | ||
| 491 | + if (r == 0) | ||
| 492 | + break; | ||
| 493 | + if (r == -ENOMEM) | ||
| 494 | + return log_oom(); | ||
| 495 | + if (r < 0) { | ||
| 496 | + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); | ||
| 497 | + break; | ||
| 498 | + } | ||
| 499 | + | ||
| 500 | + r = unit_full_printf(u, word, &k); | ||
| 501 | + if (r < 0) { | ||
| 502 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); | ||
| 503 | + continue; | ||
| 504 | + } | ||
| 505 | + | ||
| 506 | + if (!valid_user_group_name_or_id(k)) { | ||
| 507 | + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); | ||
| 508 | + continue; | ||
| 509 | + } | ||
| 510 | + | ||
| 511 | + r = strv_push(users, k); | ||
| 512 | + if (r < 0) | ||
| 513 | + return log_oom(); | ||
| 514 | + | ||
| 515 | + k = NULL; | ||
| 516 | + } | ||
| 517 | + | ||
| 518 | + return 0; | ||
| 519 | +} | ||
| 520 | + | ||
| 521 | int config_parse_busname_service( | ||
| 522 | const char *unit, | ||
| 523 | const char *filename, | ||
| 524 | diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h | ||
| 525 | index b36a2e3a0..213bce55a 100644 | ||
| 526 | --- a/src/core/load-fragment.h | ||
| 527 | +++ b/src/core/load-fragment.h | ||
| 528 | @@ -111,6 +111,8 @@ int config_parse_exec_utmp_mode(const char *unit, const char *filename, unsigned | ||
| 529 | int config_parse_working_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); | ||
| 530 | int config_parse_fdname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); | ||
| 531 | int config_parse_sec_fix_0(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); | ||
| 532 | +int config_parse_user_group(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); | ||
| 533 | +int config_parse_user_group_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); | ||
| 534 | |||
| 535 | /* gperf prototypes */ | ||
| 536 | const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, unsigned length); | ||
| 537 | -- | ||
| 538 | 2.11.0 | ||
| 539 | |||
| 540 | |||
| 541 | From 97e0456384ed5c930394062d340237ea6130ece0 Mon Sep 17 00:00:00 2001 | ||
| 542 | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||
| 543 | Date: Thu, 6 Jul 2017 13:28:19 -0400 | ||
| 544 | Subject: [PATCH 3/3] core/load-fragment: refuse units with errors in certain | ||
| 545 | directives | ||
| 546 | |||
| 547 | If an error is encountered in any of the Exec* lines, WorkingDirectory, | ||
| 548 | SELinuxContext, ApparmorProfile, SmackProcessLabel, Service (in .socket | ||
| 549 | units), User, or Group, refuse to load the unit. If the config stanza | ||
| 550 | has support, ignore the failure if '-' is present. | ||
| 551 | |||
| 552 | For those configuration directives, even if we started the unit, it's | ||
| 553 | pretty likely that it'll do something unexpected (like write files | ||
| 554 | in a wrong place, or with a wrong context, or run with wrong permissions, | ||
| 555 | etc). It seems better to refuse to start the unit and have the admin | ||
| 556 | clean up the configuration without giving the service a chance to mess | ||
| 557 | up stuff. | ||
| 558 | |||
| 559 | Note that all "security" options that restrict what the unit can do | ||
| 560 | (Capabilities, AmbientCapabilities, Restrict*, SystemCallFilter, Limit*, | ||
| 561 | PrivateDevices, Protect*, etc) are _not_ treated like this. Such options are | ||
| 562 | only supplementary, and are not always available depending on the architecture | ||
| 563 | and compilation options, so unit authors have to make sure that the service | ||
| 564 | runs correctly without them anyway. | ||
| 565 | |||
| 566 | Fixes #6237, #6277. | ||
| 567 | |||
| 568 | Signed-off-by: Ross Burton <ross.burton@intel.com> | ||
| 569 | --- | ||
| 570 | src/core/load-fragment.c | 101 ++++++++++++++++++++++++++++------------------ | ||
| 571 | src/test/test-unit-file.c | 14 +++---- | ||
| 572 | 2 files changed, 69 insertions(+), 46 deletions(-) | ||
| 573 | |||
| 574 | diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c | ||
| 575 | index f43781803..b1fb1d407 100644 | ||
| 576 | --- a/src/core/load-fragment.c | ||
| 577 | +++ b/src/core/load-fragment.c | ||
| 578 | @@ -626,20 +626,28 @@ int config_parse_exec( | ||
| 579 | |||
| 580 | if (isempty(f)) { | ||
| 581 | /* First word is either "-" or "@" with no command. */ | ||
| 582 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Empty path in command line, ignoring: \"%s\"", rvalue); | ||
| 583 | - return 0; | ||
| 584 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 585 | + "Empty path in command line%s: \"%s\"", | ||
| 586 | + ignore ? ", ignoring" : "", rvalue); | ||
| 587 | + return ignore ? 0 : -ENOEXEC; | ||
| 588 | } | ||
| 589 | if (!string_is_safe(f)) { | ||
| 590 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path contains special characters, ignoring: %s", rvalue); | ||
| 591 | - return 0; | ||
| 592 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 593 | + "Executable path contains special characters%s: %s", | ||
| 594 | + ignore ? ", ignoring" : "", rvalue); | ||
| 595 | + return ignore ? 0 : -ENOEXEC; | ||
| 596 | } | ||
| 597 | if (!path_is_absolute(f)) { | ||
| 598 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path is not absolute, ignoring: %s", rvalue); | ||
| 599 | - return 0; | ||
| 600 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 601 | + "Executable path is not absolute%s: %s", | ||
| 602 | + ignore ? ", ignoring" : "", rvalue); | ||
| 603 | + return ignore ? 0 : -ENOEXEC; | ||
| 604 | } | ||
| 605 | if (endswith(f, "/")) { | ||
| 606 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Executable path specifies a directory, ignoring: %s", rvalue); | ||
| 607 | - return 0; | ||
| 608 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 609 | + "Executable path specifies a directory%s: %s", | ||
| 610 | + ignore ? ", ignoring" : "", rvalue); | ||
| 611 | + return ignore ? 0 : -ENOEXEC; | ||
| 612 | } | ||
| 613 | |||
| 614 | if (f == firstword) { | ||
| 615 | @@ -695,7 +703,7 @@ int config_parse_exec( | ||
| 616 | if (r == 0) | ||
| 617 | break; | ||
| 618 | else if (r < 0) | ||
| 619 | - return 0; | ||
| 620 | + return ignore ? 0 : -ENOEXEC; | ||
| 621 | |||
| 622 | if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) | ||
| 623 | return log_oom(); | ||
| 624 | @@ -705,8 +713,10 @@ int config_parse_exec( | ||
| 625 | } | ||
| 626 | |||
| 627 | if (!n || !n[0]) { | ||
| 628 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Empty executable name or zeroeth argument, ignoring: %s", rvalue); | ||
| 629 | - return 0; | ||
| 630 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 631 | + "Empty executable name or zeroeth argument%s: %s", | ||
| 632 | + ignore ? ", ignoring" : "", rvalue); | ||
| 633 | + return ignore ? 0 : -ENOEXEC; | ||
| 634 | } | ||
| 635 | |||
| 636 | nce = new0(ExecCommand, 1); | ||
| 637 | @@ -1214,8 +1224,10 @@ int config_parse_exec_selinux_context( | ||
| 638 | |||
| 639 | r = unit_name_printf(u, rvalue, &k); | ||
| 640 | if (r < 0) { | ||
| 641 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); | ||
| 642 | - return 0; | ||
| 643 | + log_syntax(unit, LOG_ERR, filename, line, r, | ||
| 644 | + "Failed to resolve specifiers%s: %m", | ||
| 645 | + ignore ? ", ignoring" : ""); | ||
| 646 | + return ignore ? 0 : -ENOEXEC; | ||
| 647 | } | ||
| 648 | |||
| 649 | free(c->selinux_context); | ||
| 650 | @@ -1262,8 +1274,10 @@ int config_parse_exec_apparmor_profile( | ||
| 651 | |||
| 652 | r = unit_name_printf(u, rvalue, &k); | ||
| 653 | if (r < 0) { | ||
| 654 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); | ||
| 655 | - return 0; | ||
| 656 | + log_syntax(unit, LOG_ERR, filename, line, r, | ||
| 657 | + "Failed to resolve specifiers%s: %m", | ||
| 658 | + ignore ? ", ignoring" : ""); | ||
| 659 | + return ignore ? 0 : -ENOEXEC; | ||
| 660 | } | ||
| 661 | |||
| 662 | free(c->apparmor_profile); | ||
| 663 | @@ -1310,8 +1324,10 @@ int config_parse_exec_smack_process_label( | ||
| 664 | |||
| 665 | r = unit_name_printf(u, rvalue, &k); | ||
| 666 | if (r < 0) { | ||
| 667 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m"); | ||
| 668 | - return 0; | ||
| 669 | + log_syntax(unit, LOG_ERR, filename, line, r, | ||
| 670 | + "Failed to resolve specifiers%s: %m", | ||
| 671 | + ignore ? ", ignoring" : ""); | ||
| 672 | + return ignore ? 0 : -ENOEXEC; | ||
| 673 | } | ||
| 674 | |||
| 675 | free(c->smack_process_label); | ||
| 676 | @@ -1520,19 +1536,19 @@ int config_parse_socket_service( | ||
| 677 | |||
| 678 | r = unit_name_printf(UNIT(s), rvalue, &p); | ||
| 679 | if (r < 0) { | ||
| 680 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue); | ||
| 681 | - return 0; | ||
| 682 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers: %s", rvalue); | ||
| 683 | + return -ENOEXEC; | ||
| 684 | } | ||
| 685 | |||
| 686 | if (!endswith(p, ".service")) { | ||
| 687 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service, ignoring: %s", rvalue); | ||
| 688 | - return 0; | ||
| 689 | + log_syntax(unit, LOG_ERR, filename, line, 0, "Unit must be of type service: %s", rvalue); | ||
| 690 | + return -ENOEXEC; | ||
| 691 | } | ||
| 692 | |||
| 693 | r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x); | ||
| 694 | if (r < 0) { | ||
| 695 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r)); | ||
| 696 | - return 0; | ||
| 697 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s: %s", rvalue, bus_error_message(&error, r)); | ||
| 698 | + return -ENOEXEC; | ||
| 699 | } | ||
| 700 | |||
| 701 | unit_ref_set(&s->service, x); | ||
| 702 | @@ -1787,13 +1803,13 @@ int config_parse_user_group( | ||
| 703 | |||
| 704 | r = unit_full_printf(u, rvalue, &k); | ||
| 705 | if (r < 0) { | ||
| 706 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); | ||
| 707 | - return 0; | ||
| 708 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", rvalue); | ||
| 709 | + return -ENOEXEC; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (!valid_user_group_name_or_id(k)) { | ||
| 713 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); | ||
| 714 | - return 0; | ||
| 715 | + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); | ||
| 716 | + return -ENOEXEC; | ||
| 717 | } | ||
| 718 | |||
| 719 | n = k; | ||
| 720 | @@ -1851,19 +1867,19 @@ int config_parse_user_group_strv( | ||
| 721 | if (r == -ENOMEM) | ||
| 722 | return log_oom(); | ||
| 723 | if (r < 0) { | ||
| 724 | - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); | ||
| 725 | - break; | ||
| 726 | + log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue); | ||
| 727 | + return -ENOEXEC; | ||
| 728 | } | ||
| 729 | |||
| 730 | r = unit_full_printf(u, word, &k); | ||
| 731 | if (r < 0) { | ||
| 732 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", word); | ||
| 733 | - continue; | ||
| 734 | + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in %s: %m", word); | ||
| 735 | + return -ENOEXEC; | ||
| 736 | } | ||
| 737 | |||
| 738 | if (!valid_user_group_name_or_id(k)) { | ||
| 739 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID, ignoring: %s", k); | ||
| 740 | - continue; | ||
| 741 | + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); | ||
| 742 | + return -ENOEXEC; | ||
| 743 | } | ||
| 744 | |||
| 745 | r = strv_push(users, k); | ||
| 746 | @@ -2022,20 +2038,24 @@ int config_parse_working_directory( | ||
| 747 | |||
| 748 | r = unit_full_printf(u, rvalue, &k); | ||
| 749 | if (r < 0) { | ||
| 750 | - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers in working directory path '%s', ignoring: %m", rvalue); | ||
| 751 | - return 0; | ||
| 752 | + log_syntax(unit, LOG_ERR, filename, line, r, | ||
| 753 | + "Failed to resolve unit specifiers in working directory path '%s'%s: %m", | ||
| 754 | + rvalue, missing_ok ? ", ignoring" : ""); | ||
| 755 | + return missing_ok ? 0 : -ENOEXEC; | ||
| 756 | } | ||
| 757 | |||
| 758 | path_kill_slashes(k); | ||
| 759 | |||
| 760 | if (!utf8_is_valid(k)) { | ||
| 761 | log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); | ||
| 762 | - return 0; | ||
| 763 | + return missing_ok ? 0 : -ENOEXEC; | ||
| 764 | } | ||
| 765 | |||
| 766 | if (!path_is_absolute(k)) { | ||
| 767 | - log_syntax(unit, LOG_ERR, filename, line, 0, "Working directory path '%s' is not absolute, ignoring.", rvalue); | ||
| 768 | - return 0; | ||
| 769 | + log_syntax(unit, LOG_ERR, filename, line, 0, | ||
| 770 | + "Working directory path '%s' is not absolute%s.", | ||
| 771 | + rvalue, missing_ok ? ", ignoring" : ""); | ||
| 772 | + return missing_ok ? 0 : -ENOEXEC; | ||
| 773 | } | ||
| 774 | |||
| 775 | free(c->working_directory); | ||
| 776 | @@ -4043,8 +4063,11 @@ int unit_load_fragment(Unit *u) { | ||
| 777 | return r; | ||
| 778 | |||
| 779 | r = load_from_path(u, k); | ||
| 780 | - if (r < 0) | ||
| 781 | + if (r < 0) { | ||
| 782 | + if (r == -ENOEXEC) | ||
| 783 | + log_unit_notice(u, "Unit configuration has fatal error, unit will not be started."); | ||
| 784 | return r; | ||
| 785 | + } | ||
| 786 | |||
| 787 | if (u->load_state == UNIT_STUB) { | ||
| 788 | SET_FOREACH(t, u->names, i) { | ||
| 789 | diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c | ||
| 790 | index ade0ff2a6..fe1969570 100644 | ||
| 791 | --- a/src/test/test-unit-file.c | ||
| 792 | +++ b/src/test/test-unit-file.c | ||
| 793 | @@ -146,7 +146,7 @@ static void test_config_parse_exec(void) { | ||
| 794 | r = config_parse_exec(NULL, "fake", 4, "section", 1, | ||
| 795 | "LValue", 0, "/RValue/ argv0 r1", | ||
| 796 | &c, u); | ||
| 797 | - assert_se(r == 0); | ||
| 798 | + assert_se(r == -ENOEXEC); | ||
| 799 | assert_se(c1->command_next == NULL); | ||
| 800 | |||
| 801 | log_info("/* honour_argv0 */"); | ||
| 802 | @@ -161,7 +161,7 @@ static void test_config_parse_exec(void) { | ||
| 803 | r = config_parse_exec(NULL, "fake", 3, "section", 1, | ||
| 804 | "LValue", 0, "@/RValue", | ||
| 805 | &c, u); | ||
| 806 | - assert_se(r == 0); | ||
| 807 | + assert_se(r == -ENOEXEC); | ||
| 808 | assert_se(c1->command_next == NULL); | ||
| 809 | |||
| 810 | log_info("/* no command, whitespace only, reset */"); | ||
| 811 | @@ -220,7 +220,7 @@ static void test_config_parse_exec(void) { | ||
| 812 | "-@/RValue argv0 r1 ; ; " | ||
| 813 | "/goo/goo boo", | ||
| 814 | &c, u); | ||
| 815 | - assert_se(r >= 0); | ||
| 816 | + assert_se(r == -ENOEXEC); | ||
| 817 | c1 = c1->command_next; | ||
| 818 | check_execcommand(c1, "/RValue", "argv0", "r1", NULL, true); | ||
| 819 | |||
| 820 | @@ -374,7 +374,7 @@ static void test_config_parse_exec(void) { | ||
| 821 | r = config_parse_exec(NULL, "fake", 4, "section", 1, | ||
| 822 | "LValue", 0, path, | ||
| 823 | &c, u); | ||
| 824 | - assert_se(r == 0); | ||
| 825 | + assert_se(r == -ENOEXEC); | ||
| 826 | assert_se(c1->command_next == NULL); | ||
| 827 | } | ||
| 828 | |||
| 829 | @@ -401,21 +401,21 @@ static void test_config_parse_exec(void) { | ||
| 830 | r = config_parse_exec(NULL, "fake", 4, "section", 1, | ||
| 831 | "LValue", 0, "/path\\", | ||
| 832 | &c, u); | ||
| 833 | - assert_se(r == 0); | ||
| 834 | + assert_se(r == -ENOEXEC); | ||
| 835 | assert_se(c1->command_next == NULL); | ||
| 836 | |||
| 837 | log_info("/* missing ending ' */"); | ||
| 838 | r = config_parse_exec(NULL, "fake", 4, "section", 1, | ||
| 839 | "LValue", 0, "/path 'foo", | ||
| 840 | &c, u); | ||
| 841 | - assert_se(r == 0); | ||
| 842 | + assert_se(r == -ENOEXEC); | ||
| 843 | assert_se(c1->command_next == NULL); | ||
| 844 | |||
| 845 | log_info("/* missing ending ' with trailing backslash */"); | ||
| 846 | r = config_parse_exec(NULL, "fake", 4, "section", 1, | ||
| 847 | "LValue", 0, "/path 'foo\\", | ||
| 848 | &c, u); | ||
| 849 | - assert_se(r == 0); | ||
| 850 | + assert_se(r == -ENOEXEC); | ||
| 851 | assert_se(c1->command_next == NULL); | ||
| 852 | |||
| 853 | log_info("/* invalid space between modifiers */"); | ||
| 854 | -- | ||
| 855 | 2.11.0 | ||
| 856 | |||
diff --git a/meta/recipes-core/systemd/systemd_230.bb b/meta/recipes-core/systemd/systemd_230.bb index 702e377264..40f1428340 100644 --- a/meta/recipes-core/systemd/systemd_230.bb +++ b/meta/recipes-core/systemd/systemd_230.bb | |||
| @@ -36,6 +36,7 @@ SRC_URI += " \ | |||
| 36 | file://0022-socket-util-don-t-fail-if-libc-doesn-t-support-IDN.patch \ | 36 | file://0022-socket-util-don-t-fail-if-libc-doesn-t-support-IDN.patch \ |
| 37 | file://udev-re-enable-mount-propagation-for-udevd.patch \ | 37 | file://udev-re-enable-mount-propagation-for-udevd.patch \ |
| 38 | file://CVE-2016-7795.patch \ | 38 | file://CVE-2016-7795.patch \ |
| 39 | file://validate-user.patch \ | ||
| 39 | " | 40 | " |
| 40 | SRC_URI_append_libc-uclibc = "\ | 41 | SRC_URI_append_libc-uclibc = "\ |
| 41 | file://0002-units-Prefer-getty-to-agetty-in-console-setup-system.patch \ | 42 | file://0002-units-Prefer-getty-to-agetty-in-console-setup-system.patch \ |
