From 6483ad89f5563494190e5ada179ac98b8204c3e9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 20 Dec 2016 05:09:59 -0500 Subject: [PATCH] systemctl: do not segfault when we cannot find template unit (#4915) Core was generated by `systemctl cat test@.target test@.service'. Program terminated with signal SIGSEGV, Segmentation fault. 32 movdqu (%rdi), %xmm0 (gdb) bt -0 strrchr () at ../sysdeps/x86_64/strrchr.S:32 -1 0x00007f57fdf837fe in __GI___basename (filename=0x0) at basename.c:24 -2 0x000055b8a77d0d91 in unit_find_paths (bus=0x55b8a9242f90, unit_name=0x55b8a92428f0 "test@.service", lp=0x7ffdc9070400, fragment_path=0x7ffdc90703e0, dropin_paths=0x7ffdc90703e8) at src/systemctl/systemctl.c:2584 -3 0x000055b8a77dbae5 in cat (argc=3, argv=0x7ffdc9070678, userdata=0x0) at src/systemctl/systemctl.c:5324 -4 0x00007f57fe55fc6b in dispatch_verb (argc=5, argv=0x7ffdc9070668, verbs=0x55b8a77f1c60 , userdata=0x0) at src/basic/verbs.c:92 -5 0x000055b8a77e477f in systemctl_main (argc=5, argv=0x7ffdc9070668) at src/systemctl/systemctl.c:8141 -6 0x000055b8a77e5572 in main (argc=5, argv=0x7ffdc9070668) at src/systemctl/systemctl.c:8412 The right behaviour is not easy in this case. Implement some "sensible" logic. Fixes #4912. --- src/systemctl/systemctl.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 67516cf..f7e85c1 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -2559,6 +2559,7 @@ static int unit_find_paths( } } else { _cleanup_set_free_ Set *names; + _cleanup_free_ char *template = NULL; names = set_new(NULL); if (!names) @@ -2569,8 +2570,6 @@ static int unit_find_paths( return r; if (r == 0) { - _cleanup_free_ char *template = NULL; - r = unit_name_template(unit_name, &template); if (r < 0 && r != -EINVAL) return log_error_errno(r, "Failed to determine template name: %m"); @@ -2581,7 +2580,22 @@ static int unit_find_paths( } } - r = set_put(names, basename(path)); + if (path) + /* We found the unit file. If we followed symlinks, this name might be + * different then the unit_name with started with. Look for dropins matching + * that "final" name. */ + r = set_put(names, basename(path)); + else if (!template) + /* No unit file, let's look for dropins matching the original name. + * systemd has fairly complicated rules (based on unit type and provenience), + * which units are allowed not to have the main unit file. We err on the + * side of including too many files, and always try to load dropins. */ + r = set_put(names, unit_name); + else + /* The cases where we allow a unit to exist without the main file are + * never valid for templates. Don't try to load dropins in this case. */ + goto not_found; + if (r < 0) return log_error_errno(r, "Failed to add unit name: %m"); @@ -2605,7 +2619,7 @@ static int unit_find_paths( dropins = NULL; r = 1; } - + not_found: if (r == 0 && !arg_force) log_error("No files found for %s.", unit_name); -- 2.7.4