Zbigniew Jędrzejewski-Szmek a48f80
From f7981f669621f3873c2182cac08a39086acf3a84 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek a48f80
From: Martin Pitt <martin.pitt@ubuntu.com>
Zbigniew Jędrzejewski-Szmek a48f80
Date: Thu, 14 May 2015 09:06:40 +0200
Zbigniew Jędrzejewski-Szmek a48f80
Subject: [PATCH] core: Fix assertion with empty Exec*= paths
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
An Exec*= line with whitespace after modifiers, like
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
  ExecStart=- /bin/true
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
is considered to have an empty command path. This is as specified, but causes
Zbigniew Jędrzejewski-Szmek a48f80
systemd to crash with
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
  Assertion 'skip < l' failed at ../src/core/load-fragment.c:607, function config_parse_exec(). Aborting.
Zbigniew Jędrzejewski-Szmek a48f80
  Aborted (core dumped)
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
Fix this by logging an error instead and ignoring the invalid line.
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
Add corresponding test cases. Also add a test case for a completely empty value
Zbigniew Jędrzejewski-Szmek a48f80
which resets the command list.
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
https://launchpad.net/bugs/1454173
Zbigniew Jędrzejewski-Szmek a48f80
(cherry picked from commit 35b1078e1c375df244e19961792aeb78ca34bb54)
Zbigniew Jędrzejewski-Szmek a48f80
---
Zbigniew Jędrzejewski-Szmek a48f80
 src/core/load-fragment.c  |  6 +++++-
Zbigniew Jędrzejewski-Szmek a48f80
 src/test/test-unit-file.c | 21 +++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek a48f80
 2 files changed, 26 insertions(+), 1 deletion(-)
Zbigniew Jędrzejewski-Szmek a48f80
Zbigniew Jędrzejewski-Szmek a48f80
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
Zbigniew Jędrzejewski-Szmek a48f80
index f17a82fcdf..ec4cf4eefa 100644
Zbigniew Jędrzejewski-Szmek a48f80
--- a/src/core/load-fragment.c
Zbigniew Jędrzejewski-Szmek a48f80
+++ b/src/core/load-fragment.c
Zbigniew Jędrzejewski-Szmek a48f80
@@ -604,7 +604,11 @@ int config_parse_exec(const char *unit,
Zbigniew Jędrzejewski-Szmek a48f80
                                 skip = separate_argv0 + ignore;
Zbigniew Jędrzejewski-Szmek a48f80
 
Zbigniew Jędrzejewski-Szmek a48f80
                                 /* skip special chars in the beginning */
Zbigniew Jędrzejewski-Szmek a48f80
-                                assert(skip < l);
Zbigniew Jędrzejewski-Szmek a48f80
+                                if (l <= skip) {
Zbigniew Jędrzejewski-Szmek a48f80
+                                        log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Empty path in command line, ignoring: %s", rvalue);
Zbigniew Jędrzejewski-Szmek a48f80
+                                        r = 0;
Zbigniew Jędrzejewski-Szmek a48f80
+                                        goto fail;
Zbigniew Jędrzejewski-Szmek a48f80
+                                }
Zbigniew Jędrzejewski-Szmek a48f80
 
Zbigniew Jędrzejewski-Szmek a48f80
                         } else if (strneq(word, ";", MAX(l, 1U)))
Zbigniew Jędrzejewski-Szmek a48f80
                                 /* new commandline */
Zbigniew Jędrzejewski-Szmek a48f80
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek a48f80
index 9f3e3a227e..5500983322 100644
Zbigniew Jędrzejewski-Szmek a48f80
--- a/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek a48f80
+++ b/src/test/test-unit-file.c
Zbigniew Jędrzejewski-Szmek a48f80
@@ -318,6 +318,27 @@ static void test_config_parse_exec(void) {
Zbigniew Jędrzejewski-Szmek a48f80
         assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek a48f80
         assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek a48f80
 
Zbigniew Jędrzejewski-Szmek a48f80
+        log_info("/* invalid space between modifiers */");
Zbigniew Jędrzejewski-Szmek a48f80
+        r = config_parse_exec(NULL, "fake", 4, "section", 1,
Zbigniew Jędrzejewski-Szmek a48f80
+                              "LValue", 0, "- /path",
Zbigniew Jędrzejewski-Szmek a48f80
+                              &c, NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+
Zbigniew Jędrzejewski-Szmek a48f80
+        log_info("/* only modifiers, no path */");
Zbigniew Jędrzejewski-Szmek a48f80
+        r = config_parse_exec(NULL, "fake", 4, "section", 1,
Zbigniew Jędrzejewski-Szmek a48f80
+                              "LValue", 0, "-",
Zbigniew Jędrzejewski-Szmek a48f80
+                              &c, NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(c1->command_next == NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+
Zbigniew Jędrzejewski-Szmek a48f80
+        log_info("/* empty argument, reset */");
Zbigniew Jędrzejewski-Szmek a48f80
+        r = config_parse_exec(NULL, "fake", 4, "section", 1,
Zbigniew Jędrzejewski-Szmek a48f80
+                              "LValue", 0, "",
Zbigniew Jędrzejewski-Szmek a48f80
+                              &c, NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(r == 0);
Zbigniew Jędrzejewski-Szmek a48f80
+        assert_se(c == NULL);
Zbigniew Jędrzejewski-Szmek a48f80
+
Zbigniew Jędrzejewski-Szmek a48f80
         exec_command_free_list(c);
Zbigniew Jędrzejewski-Szmek a48f80
 }
Zbigniew Jędrzejewski-Szmek a48f80