]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/load-fragment.c
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[thirdparty/systemd.git] / src / core / load-fragment.c
index 220e617699e22fed843a8c0a25ef25ace45607d8..be4af94fc8f6169ce119f6a858b1652d83a5e85e 100644 (file)
@@ -64,6 +64,7 @@
 #include "securebits.h"
 #include "securebits-util.h"
 #include "signal-util.h"
+#include "socket-protocol-list.h"
 #include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "utf8.h"
 #include "web-util.h"
 
-int config_parse_warn_compat(
-                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) {
-        Disabled reason = ltype;
-
-        switch(reason) {
-        case DISABLED_CONFIGURATION:
-                log_syntax(unit, LOG_DEBUG, filename, line, 0,
-                           "Support for option %s= has been disabled at compile time and it is ignored", lvalue);
-                break;
-        case DISABLED_LEGACY:
-                log_syntax(unit, LOG_INFO, filename, line, 0,
-                           "Support for option %s= has been removed and it is ignored", lvalue);
-                break;
-        case DISABLED_EXPERIMENTAL:
-                log_syntax(unit, LOG_INFO, filename, line, 0,
-                           "Support for option %s= has not yet been enabled and it is ignored", lvalue);
-                break;
-        };
-
-        return 0;
-}
-
 DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
 
 int config_parse_unit_deps(
@@ -256,11 +226,19 @@ int config_parse_unit_path_printf(
         assert(rvalue);
         assert(u);
 
+        /* Let's not bother with anything that is too long */
+        if (strlen(rvalue) >= PATH_MAX) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "%s value too long%s.",
+                           lvalue, fatal ? "" : ", ignoring");
+                return fatal ? -ENAMETOOLONG : 0;
+        }
+
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, r,
-                           "Failed to resolve unit specifiers on %s%s: %m",
-                           fatal ? "" : ", ignoring", rvalue);
+                           "Failed to resolve unit specifiers in \"%s\"%s: %m",
+                           rvalue, fatal ? "" : ", ignoring");
                 return fatal ? -ENOEXEC : 0;
         }
 
@@ -409,7 +387,6 @@ int config_parse_socket_listen(const char *unit,
                 if (r < 0) {
                         if (r != -EAFNOSUPPORT)
                                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address value, ignoring: %s", rvalue);
-
                         return 0;
                 }
 
@@ -433,11 +410,9 @@ int config_parse_socket_listen(const char *unit,
         p->n_auxiliary_fds = 0;
         p->socket = s;
 
-        if (s->ports) {
-                LIST_FIND_TAIL(port, s->ports, tail);
-                LIST_INSERT_AFTER(port, s->ports, tail, p);
-        } else
-                LIST_PREPEND(port, s->ports, p);
+        LIST_FIND_TAIL(port, s->ports, tail);
+        LIST_INSERT_AFTER(port, s->ports, tail, p);
+
         p = NULL;
 
         return 0;
@@ -454,6 +429,7 @@ int config_parse_socket_protocol(const char *unit,
                                  void *data,
                                  void *userdata) {
         Socket *s;
+        int r;
 
         assert(filename);
         assert(lvalue);
@@ -462,15 +438,17 @@ int config_parse_socket_protocol(const char *unit,
 
         s = SOCKET(data);
 
-        if (streq(rvalue, "udplite"))
-                s->socket_protocol = IPPROTO_UDPLITE;
-        else if (streq(rvalue, "sctp"))
-                s->socket_protocol = IPPROTO_SCTP;
-        else {
+        r = socket_protocol_from_name(rvalue);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid socket protocol, ignoring: %s", rvalue);
+                return 0;
+        } else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
                 return 0;
         }
 
+        s->socket_protocol = r;
+
         return 0;
 }
 
@@ -495,19 +473,13 @@ int config_parse_socket_bind(const char *unit,
 
         s = SOCKET(data);
 
-        b = socket_address_bind_ipv6_only_from_string(rvalue);
+        b = parse_socket_address_bind_ipv6_only_or_bool(rvalue);
         if (b < 0) {
-                int r;
-
-                r = parse_boolean(rvalue);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
-                        return 0;
-                }
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
+                return 0;
+        }
 
-                s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
-        } else
-                s->bind_ipv6_only = b;
+        s->bind_ipv6_only = b;
 
         return 0;
 }
@@ -759,9 +731,9 @@ int config_parse_exec(
 
                         if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
                                 return log_oom();
-                        n[nlen++] = resolved;
+
+                        n[nlen++] = TAKE_PTR(resolved);
                         n[nlen] = NULL;
-                        resolved = NULL;
                 }
 
                 if (!n || !n[0]) {
@@ -775,15 +747,13 @@ int config_parse_exec(
                 if (!nce)
                         return log_oom();
 
-                nce->argv = n;
-                nce->path = path;
+                nce->argv = TAKE_PTR(n);
+                nce->path = TAKE_PTR(path);
                 nce->flags = flags;
 
                 exec_command_append_list(e, nce);
 
                 /* Do not _cleanup_free_ these. */
-                n = NULL;
-                path = NULL;
                 nce = NULL;
 
                 rvalue = p;
@@ -978,7 +948,6 @@ int config_parse_exec_input_data(
                 void *data,
                 void *userdata) {
 
-        _cleanup_free_ char *cleaned = NULL;
         _cleanup_free_ void *p = NULL;
         ExecContext *c = data;
         size_t sz;
@@ -997,15 +966,9 @@ int config_parse_exec_input_data(
                 return 0;
         }
 
-        /* Be tolerant to whitespace. Remove it all before decoding */
-        cleaned = strdup(rvalue);
-        if (!cleaned)
-                return log_oom();
-        delete_chars(cleaned, WHITESPACE);
-
-        r = unbase64mem(cleaned, (size_t) -1, &p, &sz);
+        r = unbase64mem(rvalue, (size_t) -1, &p, &sz);
         if (r < 0)
-                return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode base64 data, ignoring: %s", cleaned);
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode base64 data, ignoring: %s", rvalue);
 
         assert(sz > 0);
 
@@ -1275,17 +1238,28 @@ int config_parse_exec_cpu_affinity(const char *unit,
         if (ncpus < 0)
                 return ncpus;
 
-        if (c->cpuset)
-                CPU_FREE(c->cpuset);
-
-        if (ncpus == 0)
+        if (ncpus == 0) {
                 /* An empty assignment resets the CPU list */
-                c->cpuset = NULL;
-        else {
-                c->cpuset = cpuset;
-                cpuset = NULL;
+                c->cpuset = cpu_set_mfree(c->cpuset);
+                c->cpuset_ncpus = 0;
+                return 0;
+        }
+
+        if (!c->cpuset) {
+                c->cpuset = TAKE_PTR(cpuset);
+                c->cpuset_ncpus = (unsigned) ncpus;
+                return 0;
+        }
+
+        if (c->cpuset_ncpus < (unsigned) ncpus) {
+                CPU_OR_S(CPU_ALLOC_SIZE(c->cpuset_ncpus), cpuset, c->cpuset, cpuset);
+                CPU_FREE(c->cpuset);
+                c->cpuset = TAKE_PTR(cpuset);
+                c->cpuset_ncpus = (unsigned) ncpus;
+                return 0;
         }
-        c->cpuset_ncpus = ncpus;
+
+        CPU_OR_S(CPU_ALLOC_SIZE((unsigned) ncpus), c->cpuset, c->cpuset, cpuset);
 
         return 0;
 }
@@ -1743,9 +1717,8 @@ int config_parse_trigger_unit(
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Unit type not valid, ignoring: %s", rvalue);
                 return 0;
         }
-
-        if (type == u->type) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Trigger cannot be of same type, ignoring: %s", rvalue);
+        if (unit_has_name(u, p)) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Units cannot trigger themselves, ignoring: %s", rvalue);
                 return 0;
         }
 
@@ -1858,7 +1831,7 @@ int config_parse_socket_service(
                 return -ENOEXEC;
         }
 
-        unit_ref_set(&s->service, x);
+        unit_ref_set(&s->service, UNIT(s), x);
 
         return 0;
 }
@@ -2112,8 +2085,7 @@ int config_parse_user_group(
                         return -ENOEXEC;
                 }
 
-                n = k;
-                k = NULL;
+                n = TAKE_PTR(k);
         }
 
         free(*user);
@@ -2343,10 +2315,8 @@ int config_parse_environ(
                                            "Failed to resolve specifiers, ignoring: %s", word);
                                 continue;
                         }
-                } else {
-                        k = word;
-                        word = NULL;
-                }
+                } else
+                        k = TAKE_PTR(word);
 
                 if (!env_assignment_is_valid(k)) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2413,10 +2383,8 @@ int config_parse_pass_environ(
                                            "Failed to resolve specifiers, ignoring: %s", word);
                                 continue;
                         }
-                } else {
-                        k = word;
-                        word = NULL;
-                }
+                } else
+                        k = TAKE_PTR(word);
 
                 if (!env_name_is_valid(k)) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2427,9 +2395,8 @@ int config_parse_pass_environ(
                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
                         return log_oom();
 
-                n[nlen++] = k;
+                n[nlen++] = TAKE_PTR(k);
                 n[nlen] = NULL;
-                k = NULL;
         }
 
         if (n) {
@@ -2492,10 +2459,8 @@ int config_parse_unset_environ(
                                            "Failed to resolve specifiers, ignoring: %s", word);
                                 continue;
                         }
-                } else {
-                        k = word;
-                        word = NULL;
-                }
+                } else
+                        k = TAKE_PTR(word);
 
                 if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) {
                         log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -2506,9 +2471,8 @@ int config_parse_unset_environ(
                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
                         return log_oom();
 
-                n[nlen++] = k;
+                n[nlen++] = TAKE_PTR(k);
                 n[nlen] = NULL;
-                k = NULL;
         }
 
         if (n) {
@@ -2579,7 +2543,7 @@ int config_parse_log_extra_fields(
                         continue;
                 }
 
-                t = realloc_multiply(c->log_extra_fields, sizeof(struct iovec), c->n_log_extra_fields+1);
+                t = reallocarray(c->log_extra_fields, c->n_log_extra_fields+1, sizeof(struct iovec));
                 if (!t)
                         return log_oom();
 
@@ -2885,60 +2849,6 @@ int config_parse_documentation(const char *unit,
 }
 
 #if HAVE_SECCOMP
-
-static int syscall_filter_parse_one(
-                const char *unit,
-                const char *filename,
-                unsigned line,
-                ExecContext *c,
-                bool invert,
-                const char *t,
-                bool warn,
-                int errno_num) {
-        int r;
-
-        if (t[0] == '@') {
-                const SyscallFilterSet *set;
-                const char *i;
-
-                set = syscall_filter_set_find(t);
-                if (!set) {
-                        if (warn)
-                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown system call group, ignoring: %s", t);
-                        return 0;
-                }
-
-                NULSTR_FOREACH(i, set->value) {
-                        r = syscall_filter_parse_one(unit, filename, line, c, invert, i, false, errno_num);
-                        if (r < 0)
-                                return r;
-                }
-        } else {
-                int id;
-
-                id = seccomp_syscall_resolve_name(t);
-                if (id == __NR_SCMP_ERROR)  {
-                        if (warn)
-                                log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", t);
-                        return 0;
-                }
-
-                /* If we previously wanted to forbid a syscall and now
-                 * we want to allow it, then remove it from the list.
-                 */
-                if (!invert == c->syscall_whitelist) {
-                        r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
-                        if (r == 0)
-                                return 0;
-                        if (r < 0)
-                                return log_oom();
-                } else
-                        (void) hashmap_remove(c->syscall_filter, INT_TO_PTR(id + 1));
-        }
-
-        return 0;
-}
-
 int config_parse_syscall_filter(
                 const char *unit,
                 const char *filename,
@@ -2987,7 +2897,7 @@ int config_parse_syscall_filter(
                         c->syscall_whitelist = true;
 
                         /* Accept default syscalls if we are on a whitelist */
-                        r = syscall_filter_parse_one(unit, filename, line, c, false, "@default", false, -1);
+                        r = seccomp_parse_syscall_filter("@default", -1, c->syscall_filter, SECCOMP_PARSE_WHITELIST);
                         if (r < 0)
                                 return r;
                 }
@@ -3014,7 +2924,9 @@ int config_parse_syscall_filter(
                         continue;
                 }
 
-                r = syscall_filter_parse_one(unit, filename, line, c, invert, name, true, num);
+                r = seccomp_parse_syscall_filter_full(name, num, c->syscall_filter,
+                                                      SECCOMP_PARSE_LOG|SECCOMP_PARSE_PERMISSIVE|(invert ? SECCOMP_PARSE_INVERT : 0)|(c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0),
+                                                      unit, filename, line);
                 if (r < 0)
                         return r;
         }
@@ -3396,7 +3308,8 @@ int config_parse_memory_limit(
                 } else
                         bytes = physical_memory_scale(r, 100U);
 
-                if (bytes <= 0 || bytes >= UINT64_MAX) {
+                if (bytes >= UINT64_MAX ||
+                    (bytes <= 0 && !streq(lvalue, "MemorySwapMax"))) {
                         log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' out of range. Ignoring.", rvalue);
                         return 0;
                 }
@@ -3557,10 +3470,11 @@ int config_parse_device_allow(
         }
 
         r = unit_full_printf(userdata, rvalue, &t);
-        if(r < 0) {
+        if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r,
                            "Failed to resolve specifiers in %s, ignoring: %m",
                            rvalue);
+                return 0;
         }
 
         n = strcspn(t, WHITESPACE);
@@ -3569,7 +3483,8 @@ int config_parse_device_allow(
         if (!path)
                 return log_oom();
 
-        if (!is_deviceallow_pattern(path)) {
+        if (!is_deviceallow_pattern(path) &&
+            !path_startswith(path, "/run/systemd/inaccessible/")) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
                 return 0;
         }
@@ -3587,8 +3502,7 @@ int config_parse_device_allow(
         if (!a)
                 return log_oom();
 
-        a->path = path;
-        path = NULL;
+        a->path = TAKE_PTR(path);
         a->r = !!strchr(m, 'r');
         a->w = !!strchr(m, 'w');
         a->m = !!strchr(m, 'm');
@@ -3669,7 +3583,8 @@ int config_parse_io_device_weight(
         if (!path)
                 return log_oom();
 
-        if (!path_startswith(path, "/dev")) {
+        if (!path_startswith(path, "/dev") &&
+            !path_startswith(path, "/run/systemd/inaccessible/")) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
                 return 0;
         }
@@ -3686,8 +3601,7 @@ int config_parse_io_device_weight(
         if (!w)
                 return log_oom();
 
-        w->path = path;
-        path = NULL;
+        w->path = TAKE_PTR(path);
 
         w->weight = u;
 
@@ -3742,7 +3656,8 @@ int config_parse_io_limit(
         if (!path)
                 return log_oom();
 
-        if (!path_startswith(path, "/dev")) {
+        if (!path_startswith(path, "/dev") &&
+            !path_startswith(path, "/run/systemd/inaccessible/")) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
                 return 0;
         }
@@ -3771,8 +3686,7 @@ int config_parse_io_limit(
                 if (!l)
                         return log_oom();
 
-                l->path = path;
-                path = NULL;
+                l->path = TAKE_PTR(path);
                 for (ttype = 0; ttype < _CGROUP_IO_LIMIT_TYPE_MAX; ttype++)
                         l->limits[ttype] = cgroup_io_limit_defaults[ttype];
 
@@ -3856,7 +3770,8 @@ int config_parse_blockio_device_weight(
         if (!path)
                 return log_oom();
 
-        if (!path_startswith(path, "/dev")) {
+        if (!path_startswith(path, "/dev") &&
+            !path_startswith(path, "/run/systemd/inaccessible/")) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
                 return 0;
         }
@@ -3873,8 +3788,7 @@ int config_parse_blockio_device_weight(
         if (!w)
                 return log_oom();
 
-        w->path = path;
-        path = NULL;
+        w->path = TAKE_PTR(path);
 
         w->weight = u;
 
@@ -3930,7 +3844,8 @@ int config_parse_blockio_bandwidth(
         if (!path)
                 return log_oom();
 
-        if (!path_startswith(path, "/dev")) {
+        if (!path_startswith(path, "/dev") &&
+            !path_startswith(path, "/run/systemd/inaccessible/")) {
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
                 return 0;
         }
@@ -3953,8 +3868,7 @@ int config_parse_blockio_bandwidth(
                 if (!b)
                         return log_oom();
 
-                b->path = path;
-                path = NULL;
+                b->path = TAKE_PTR(path);
                 b->rbps = CGROUP_LIMIT_MAX;
                 b->wbps = CGROUP_LIMIT_MAX;
 
@@ -3996,6 +3910,8 @@ int config_parse_job_mode_isolate(
                 return 0;
         }
 
+        log_notice("%s is deprecated. Please use OnFailureJobMode= instead", lvalue);
+
         *m = r ? JOB_ISOLATE : JOB_REPLACE;
         return 0;
 }
@@ -4220,6 +4136,83 @@ int config_parse_namespace_path_strv(
         return 0;
 }
 
+int config_parse_temporary_filesystems(
+                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) {
+
+        Unit *u = userdata;
+        ExecContext *c = data;
+        const char *cur;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                /* Empty assignment resets the list */
+                temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
+                c->temporary_filesystems = NULL;
+                c->n_temporary_filesystems = 0;
+                return 0;
+        }
+
+        cur = rvalue;
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *path = NULL, *resolved = NULL;
+                const char *w;
+
+                r = extract_first_word(&cur, &word, NULL, EXTRACT_QUOTES);
+                if (r == 0)
+                        break;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
+                        return 0;
+                }
+
+                w = word;
+                r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -EINVAL;
+
+                r = unit_full_printf(u, path, &resolved);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers in %s, ignoring: %m", word);
+                        continue;
+                }
+
+                if (!path_is_absolute(resolved)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Not an absolute path, ignoring: %s", resolved);
+                        continue;
+                }
+
+                path_kill_slashes(resolved);
+
+                r = temporary_filesystem_add(&c->temporary_filesystems, &c->n_temporary_filesystems, path, w);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse mount options, ignoring: %s", word);
+                        continue;
+                }
+        }
+
+        return 0;
+}
+
 int config_parse_bind_paths(
                 const char *unit,
                 const char *filename,
@@ -4406,7 +4399,7 @@ int config_parse_protect_home(
                 void *userdata) {
 
         ExecContext *c = data;
-        int k;
+        ProtectHome h;
 
         assert(filename);
         assert(lvalue);
@@ -4416,23 +4409,14 @@ int config_parse_protect_home(
         /* Our enum shall be a superset of booleans, hence first try
          * to parse as boolean, and then as enum */
 
-        k = parse_boolean(rvalue);
-        if (k > 0)
-                c->protect_home = PROTECT_HOME_YES;
-        else if (k == 0)
-                c->protect_home = PROTECT_HOME_NO;
-        else {
-                ProtectHome h;
-
-                h = protect_home_from_string(rvalue);
-                if (h < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                c->protect_home = h;
+        h = parse_protect_home_or_bool(rvalue);
+        if (h < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect home value, ignoring: %s", rvalue);
+                return 0;
         }
 
+        c->protect_home = h;
+
         return 0;
 }
 
@@ -4449,7 +4433,7 @@ int config_parse_protect_system(
                 void *userdata) {
 
         ExecContext *c = data;
-        int k;
+        ProtectSystem s;
 
         assert(filename);
         assert(lvalue);
@@ -4459,23 +4443,14 @@ int config_parse_protect_system(
         /* Our enum shall be a superset of booleans, hence first try
          * to parse as boolean, and then as enum */
 
-        k = parse_boolean(rvalue);
-        if (k > 0)
-                c->protect_system = PROTECT_SYSTEM_YES;
-        else if (k == 0)
-                c->protect_system = PROTECT_SYSTEM_NO;
-        else {
-                ProtectSystem s;
-
-                s = protect_system_from_string(rvalue);
-                if (s < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
-                        return 0;
-                }
-
-                c->protect_system = s;
+        s = parse_protect_system_or_bool(rvalue);
+        if (s < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse protect system value, ignoring: %s", rvalue);
+                return 0;
         }
 
+        c->protect_system = s;
+
         return 0;
 }
 
@@ -4783,9 +4758,7 @@ static int load_from_path(Unit *u, const char *path) {
                         return r;
         }
 
-        free(u->fragment_path);
-        u->fragment_path = filename;
-        filename = NULL;
+        free_and_replace(u->fragment_path, filename);
 
         if (u->source_path) {
                 if (stat(u->source_path, &st) >= 0)