]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/load-fragment.c
Merge pull request #23309 from DaanDeMeyer/log-context
[thirdparty/systemd.git] / src / core / load-fragment.c
index 92e99e7d536d88e6af3a3a7a3c5f28563e563d4f..0ed2d1b31d47f043c8517b7d424df197c3719d0f 100644 (file)
 #include "missing_ioprio.h"
 #include "mountpoint-util.h"
 #include "nulstr-util.h"
+#include "open-file.h"
 #include "parse-helpers.h"
 #include "parse-util.h"
 #include "path-util.h"
+#include "pcre2-util.h"
 #include "percent-util.h"
 #include "process-util.h"
 #if HAVE_SECCOMP
 #include "seccomp-util.h"
 #endif
 #include "securebits-util.h"
+#include "selinux-util.h"
 #include "signal-util.h"
 #include "socket-netlink.h"
 #include "specifier.h"
@@ -146,12 +149,37 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_managed_oom_preference, managed_oom_prefer
 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
 DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
 DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
-DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
-DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
+DEFINE_CONFIG_PARSE_PTR(config_parse_cg_cpu_weight, cg_cpu_weight_parse, uint64_t, "Invalid CPU weight");
+static DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares_internal, cg_cpu_shares_parse, uint64_t, "Invalid CPU shares");
+DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flag_from_string, unsigned long, "Failed to parse mount flag");
 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_status_unit_format, status_unit_format, StatusUnitFormat, "Failed to parse status unit format");
 DEFINE_CONFIG_PARSE_ENUM_FULL(config_parse_socket_timestamping, socket_timestamping_from_string_harder, SocketTimestamping, "Failed to parse timestamping precision");
 
+int config_parse_cpu_shares(
+                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) {
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "Unit uses %s=; please use CPUWeight= instead. Support for %s= will be removed soon.",
+                   lvalue, lvalue);
+
+        return config_parse_cpu_shares_internal(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
+}
+
 bool contains_instance_specifier_superset(const char *s) {
         const char *p, *q;
         bool percent = false;
@@ -318,13 +346,12 @@ int config_parse_unit_string_printf(
                 void *userdata) {
 
         _cleanup_free_ char *k = NULL;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
@@ -347,14 +374,13 @@ int config_parse_unit_strv_printf(
                 void *data,
                 void *userdata) {
 
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         _cleanup_free_ char *k = NULL;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = unit_full_printf(u, rvalue, &k);
         if (r < 0) {
@@ -378,14 +404,13 @@ int config_parse_unit_path_printf(
                 void *userdata) {
 
         _cleanup_free_ char *k = NULL;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
         bool fatal = ltype;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = unit_path_printf(u, rvalue, &k);
         if (r < 0) {
@@ -409,14 +434,13 @@ int config_parse_colon_separated_paths(
                 const char *rvalue,
                 void *data,
                 void *userdata) {
-        char ***sv = data;
+        char ***sv = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -469,13 +493,12 @@ int config_parse_unit_path_strv_printf(
                 void *userdata) {
 
         char ***x = data;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 *x = strv_free(*x);
@@ -652,12 +675,12 @@ int config_parse_socket_listen(
                 p->type = SOCKET_SOCKET;
         }
 
-        p->fd = -1;
+        p->fd = -EBADF;
         p->auxiliary_fds = NULL;
         p->n_auxiliary_fds = 0;
         p->socket = s;
 
-        LIST_FIND_TAIL(port, s->ports, tail);
+        tail = LIST_FIND_TAIL(port, s->ports);
         LIST_INSERT_AFTER(port, s->ports, tail, p);
 
         p = NULL;
@@ -677,13 +700,12 @@ int config_parse_exec_nice(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int priority, r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->nice_set = false;
@@ -717,13 +739,12 @@ int config_parse_exec_oom_score_adjust(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int oa, r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->oom_score_adjust_set = false;
@@ -757,13 +778,12 @@ int config_parse_exec_coredump_filter(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->coredump_filter = 0;
@@ -817,9 +837,9 @@ int config_parse_kill_mode(
 
         if (m == KILL_NONE)
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
-                           "Unit configured to use KillMode=none. "
+                           "Unit uses KillMode=none. "
                            "This is unsafe, as it disables systemd's process lifecycle management for the service. "
-                           "Please update your service to use a safer KillMode=, such as 'mixed' or 'control-group'. "
+                           "Please update the service to use a safer KillMode=, such as 'mixed' or 'control-group'. "
                            "Support for KillMode=none is deprecated and will eventually be removed.");
 
         *k = m;
@@ -838,7 +858,7 @@ int config_parse_exec(
                 void *data,
                 void *userdata) {
 
-        ExecCommand **e = data;
+        ExecCommand **e = ASSERT_PTR(data);
         const Unit *u = userdata;
         const char *p;
         bool semicolon;
@@ -847,7 +867,6 @@ int config_parse_exec(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(e);
 
         e += ltype;
 
@@ -1053,12 +1072,11 @@ int config_parse_socket_bindtodevice(
                 void *data,
                 void *userdata) {
 
-        Socket *s = data;
+        Socket *s = ASSERT_PTR(data);
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue) || streq(rvalue, "*")) {
                 s->bind_to_device = mfree(s->bind_to_device);
@@ -1085,13 +1103,12 @@ int config_parse_exec_input(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         const char *n;
         ExecInput ei;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(rvalue);
@@ -1159,11 +1176,10 @@ int config_parse_exec_input_text(
                 void *userdata) {
 
         _cleanup_free_ char *unescaped = NULL, *resolved = NULL;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(rvalue);
@@ -1223,12 +1239,11 @@ int config_parse_exec_input_data(
                 void *userdata) {
 
         _cleanup_free_ void *p = NULL;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         size_t sz;
         void *q;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(rvalue);
@@ -1283,13 +1298,12 @@ int config_parse_exec_output(
 
         _cleanup_free_ char *resolved = NULL;
         const char *n;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         bool obsolete = false;
         ExecOutput eo;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(lvalue);
@@ -1407,13 +1421,12 @@ int config_parse_exec_io_class(const char *unit,
                                void *data,
                                void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int x;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->ioprio_set = false;
@@ -1444,13 +1457,12 @@ int config_parse_exec_io_priority(const char *unit,
                                   void *data,
                                   void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int i, r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->ioprio_set = false;
@@ -1481,13 +1493,12 @@ int config_parse_exec_cpu_sched_policy(const char *unit,
                                        void *data,
                                        void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int x;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->cpu_sched_set = false;
@@ -1521,13 +1532,12 @@ int config_parse_exec_mount_apivfs(const char *unit,
                                    void *data,
                                    void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int k;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->mount_apivfs_set = false;
@@ -1559,12 +1569,11 @@ int config_parse_numa_mask(const char *unit,
                            void *data,
                            void *userdata) {
         int r;
-        NUMAPolicy *p = data;
+        NUMAPolicy *p = ASSERT_PTR(data);
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (streq(rvalue, "all")) {
                 r = numa_mask_add_all(&p->nodes);
@@ -1591,13 +1600,12 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
                                      void *data,
                                      void *userdata) {
 
-        ExecContext *c = data;
-        int i, min, max, r;
+        ExecContext *c = ASSERT_PTR(data);
+        int i, r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         r = safe_atoi(rvalue, &i);
         if (r < 0) {
@@ -1605,11 +1613,9 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
                 return 0;
         }
 
-        /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
-        min = sched_get_priority_min(c->cpu_sched_policy);
-        max = sched_get_priority_max(c->cpu_sched_policy);
-
-        if (i < min || i > max) {
+        /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0. Policy might be set later so
+         * we do not check the precise range, but only the generic outer bounds. */
+        if (i < 0 || i > 99) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "CPU scheduling priority is out of range, ignoring: %s", rvalue);
                 return 0;
         }
@@ -1634,14 +1640,13 @@ int config_parse_root_image_options(
 
         _cleanup_(mount_options_free_allp) MountOptions *options = NULL;
         _cleanup_strv_free_ char **l = NULL;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->root_image_options = mount_options_free_all(c->root_image_options);
@@ -1713,11 +1718,10 @@ int config_parse_exec_root_hash(
                 void *userdata) {
 
         _cleanup_free_ void *roothash_decoded = NULL;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         size_t roothash_decoded_size = 0;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(rvalue);
@@ -1776,11 +1780,10 @@ int config_parse_exec_root_hash_sig(
 
         _cleanup_free_ void *roothash_sig_decoded = NULL;
         char *value;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         size_t roothash_sig_decoded_size = 0;
         int r;
 
-        assert(data);
         assert(filename);
         assert(line);
         assert(rvalue);
@@ -1839,7 +1842,7 @@ int config_parse_exec_cpu_affinity(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
         int r;
@@ -1847,7 +1850,6 @@ int config_parse_exec_cpu_affinity(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (streq(rvalue, "numa")) {
                 c->cpu_affinity_from_numa = true;
@@ -1883,7 +1885,7 @@ int config_parse_capability_set(
                 void *data,
                 void *userdata) {
 
-        uint64_t *capability_set = data;
+        uint64_t *capability_set = ASSERT_PTR(data);
         uint64_t sum = 0, initial = 0;
         bool invert = false;
         int r;
@@ -1891,7 +1893,6 @@ int config_parse_capability_set(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (rvalue[0] == '~') {
                 invert = true;
@@ -1934,7 +1935,7 @@ int config_parse_exec_selinux_context(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         bool ignore;
         char *k;
@@ -1943,7 +1944,6 @@ int config_parse_exec_selinux_context(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->selinux_context = mfree(c->selinux_context);
@@ -1983,7 +1983,7 @@ int config_parse_exec_apparmor_profile(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         bool ignore;
         char *k;
@@ -1992,7 +1992,6 @@ int config_parse_exec_apparmor_profile(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->apparmor_profile = mfree(c->apparmor_profile);
@@ -2032,7 +2031,7 @@ int config_parse_exec_smack_process_label(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         bool ignore;
         char *k;
@@ -2041,7 +2040,6 @@ int config_parse_exec_smack_process_label(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 c->smack_process_label = mfree(c->smack_process_label);
@@ -2084,7 +2082,7 @@ int config_parse_timer(
         _cleanup_(calendar_spec_freep) CalendarSpec *c = NULL;
         _cleanup_free_ char *k = NULL;
         const Unit *u = userdata;
-        Timer *t = data;
+        Timer *t = ASSERT_PTR(data);
         usec_t usec = 0;
         TimerValue *v;
         int r;
@@ -2092,7 +2090,6 @@ int config_parse_timer(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets list */
@@ -2148,14 +2145,13 @@ int config_parse_trigger_unit(
                 void *userdata) {
 
         _cleanup_free_ char *p = NULL;
-        Unit *u = data;
+        Unit *u = ASSERT_PTR(data);
         UnitType type;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (UNIT_TRIGGER(u)) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "Multiple units to trigger specified, ignoring: %s", rvalue);
@@ -2198,7 +2194,7 @@ int config_parse_path_spec(const char *unit,
                            void *data,
                            void *userdata) {
 
-        Path *p = data;
+        Path *p = ASSERT_PTR(data);
         PathSpec *s;
         PathType b;
         _cleanup_free_ char *k = NULL;
@@ -2207,7 +2203,6 @@ int config_parse_path_spec(const char *unit,
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment clears list */
@@ -2238,7 +2233,7 @@ int config_parse_path_spec(const char *unit,
         s->unit = UNIT(p);
         s->path = TAKE_PTR(k);
         s->type = b;
-        s->inotify_fd = -1;
+        s->inotify_fd = -EBADF;
 
         LIST_PREPEND(spec, p->specs, s);
 
@@ -2259,14 +2254,13 @@ int config_parse_socket_service(
 
         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_free_ char *p = NULL;
-        Socket *s = data;
+        Socket *s = ASSERT_PTR(data);
         Unit *x;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         r = unit_name_printf(UNIT(s), rvalue, &p);
         if (r < 0) {
@@ -2303,13 +2297,12 @@ int config_parse_fdname(
                 void *userdata) {
 
         _cleanup_free_ char *p = NULL;
-        Socket *s = data;
+        Socket *s = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 s->fdname = mfree(s->fdname);
@@ -2342,13 +2335,12 @@ int config_parse_service_sockets(
                 void *data,
                 void *userdata) {
 
-        Service *s = data;
+        Service *s = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         for (const char *p = rvalue;;) {
                 _cleanup_free_ char *word = NULL, *k = NULL;
@@ -2397,13 +2389,12 @@ int config_parse_bus_name(
                 void *userdata) {
 
         _cleanup_free_ char *k = NULL;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = unit_full_printf_full(u, rvalue, SD_BUS_MAXIMUM_NAME_LENGTH, &k);
         if (r < 0) {
@@ -2431,14 +2422,13 @@ int config_parse_service_timeout(
                 void *data,
                 void *userdata) {
 
-        Service *s = userdata;
+        Service *s = ASSERT_PTR(userdata);
         usec_t usec;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(s);
 
         /* This is called for two cases: TimeoutSec= and TimeoutStartSec=. */
 
@@ -2472,13 +2462,12 @@ int config_parse_timeout_abort(
                 void *data,
                 void *userdata) {
 
-        usec_t *ret = data;
+        usec_t *ret = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(ret);
 
         /* Note: apart from setting the arg, this returns an extra bit of information in the return value. */
 
@@ -2506,11 +2495,9 @@ int config_parse_service_timeout_abort(
                 void *data,
                 void *userdata) {
 
-        Service *s = userdata;
+        Service *s = ASSERT_PTR(userdata);
         int r;
 
-        assert(s);
-
         r = config_parse_timeout_abort(unit, filename, line, section, section_line, lvalue, ltype, rvalue,
                                        &s->timeout_abort_usec, s);
         if (r >= 0)
@@ -2518,37 +2505,6 @@ int config_parse_service_timeout_abort(
         return 0;
 }
 
-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) {
-
-        usec_t *usec = data;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(usec);
-
-        /* This is pretty much like config_parse_sec(), except that this treats a time of 0 as infinity, for
-         * compatibility with older versions of systemd where 0 instead of infinity was used as indicator to turn off a
-         * timeout. */
-
-        r = parse_sec_fix_0(rvalue, usec);
-        if (r < 0)
-                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s= parameter, ignoring: %s", lvalue, rvalue);
-
-        return 0;
-}
-
 int config_parse_user_group_compat(
                 const char *unit,
                 const char *filename,
@@ -2563,13 +2519,12 @@ int config_parse_user_group_compat(
 
         _cleanup_free_ char *k = NULL;
         char **user = data;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 *user = mfree(*user);
@@ -2612,13 +2567,12 @@ int config_parse_user_group_strv_compat(
                 void *userdata) {
 
         char ***users = data;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 *users = strv_free(*users);
@@ -2669,16 +2623,14 @@ int config_parse_working_directory(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
-        const Unit *u = userdata;
+        ExecContext *c = ASSERT_PTR(data);
+        const Unit *u = ASSERT_PTR(userdata);
         bool missing_ok;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(c);
-        assert(u);
 
         if (isempty(rvalue)) {
                 c->working_directory_home = false;
@@ -2729,7 +2681,7 @@ int config_parse_unit_env_file(const char *unit,
                                void *data,
                                void *userdata) {
 
-        char ***env = data;
+        char ***env = ASSERT_PTR(data);
         const Unit *u = userdata;
         _cleanup_free_ char *n = NULL;
         int r;
@@ -2737,7 +2689,6 @@ int config_parse_unit_env_file(const char *unit,
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment frees the list */
@@ -2777,13 +2728,12 @@ int config_parse_environ(
                 void *userdata) {
 
         const Unit *u = userdata;
-        char ***env = data;
+        char ***env = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -2841,14 +2791,13 @@ int config_parse_pass_environ(
 
         _cleanup_strv_free_ char **n = NULL;
         const Unit *u = userdata;
-        char*** passenv = data;
+        char*** passenv = ASSERT_PTR(data);
         size_t nlen = 0;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -2915,7 +2864,7 @@ int config_parse_unset_environ(
                 void *userdata) {
 
         _cleanup_strv_free_ char **n = NULL;
-        char*** unsetenv = data;
+        char*** unsetenv = ASSERT_PTR(data);
         const Unit *u = userdata;
         size_t nlen = 0;
         int r;
@@ -2923,7 +2872,6 @@ int config_parse_unset_environ(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -2989,14 +2937,13 @@ int config_parse_log_extra_fields(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(c);
 
         if (isempty(rvalue)) {
                 exec_context_free_log_extra_fields(c);
@@ -3059,14 +3006,13 @@ int config_parse_log_namespace(
                 void *userdata) {
 
         _cleanup_free_ char *k = NULL;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(c);
 
         if (isempty(rvalue)) {
                 c->log_namespace = mfree(c->log_namespace);
@@ -3101,7 +3047,7 @@ int config_parse_unit_condition_path(
                 void *userdata) {
 
         _cleanup_free_ char *p = NULL;
-        Condition **list = data, *c;
+        Condition **list = ASSERT_PTR(data), *c;
         ConditionType t = ltype;
         bool trigger, negate;
         const Unit *u = userdata;
@@ -3110,7 +3056,6 @@ int config_parse_unit_condition_path(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3157,7 +3102,7 @@ int config_parse_unit_condition_string(
                 void *userdata) {
 
         _cleanup_free_ char *s = NULL;
-        Condition **list = data, *c;
+        Condition **list = ASSERT_PTR(data), *c;
         ConditionType t = ltype;
         bool trigger, negate;
         const Unit *u = userdata;
@@ -3166,7 +3111,6 @@ int config_parse_unit_condition_string(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3261,14 +3205,13 @@ int config_parse_documentation(
                 void *data,
                 void *userdata) {
 
-        Unit *u = userdata;
+        Unit *u = ASSERT_PTR(userdata);
         int r;
         char **a, **b;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3310,14 +3253,13 @@ int config_parse_syscall_filter(
                 void *userdata) {
 
         ExecContext *c = data;
-        _unused_ const Unit *u = userdata;
+        _unused_ const Unit *u = ASSERT_PTR(userdata);
         bool invert = false;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3405,7 +3347,7 @@ int config_parse_syscall_log(
                 void *userdata) {
 
         ExecContext *c = data;
-        _unused_ const Unit *u = userdata;
+        _unused_ const Unit *u = ASSERT_PTR(userdata);
         bool invert = false;
         const char *p;
         int r;
@@ -3413,7 +3355,6 @@ int config_parse_syscall_log(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3700,14 +3641,13 @@ int config_parse_restrict_filesystems(
                 const char *rvalue,
                 void *data,
                 void *userdata) {
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         bool invert = false;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -3888,7 +3828,7 @@ int config_parse_memory_limit(
                         bytes = physical_memory_scale(r, 10000U);
 
                 if (bytes >= UINT64_MAX ||
-                    (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
+                    (bytes <= 0 && !STR_IN_SET(lvalue, "MemorySwapMax", "MemoryZSwapMax", "MemoryLow", "MemoryMin", "DefaultMemoryLow", "DefaultMemoryMin"))) {
                         log_syntax(unit, LOG_WARNING, filename, line, 0, "Memory limit '%s' out of range, ignoring.", rvalue);
                         return 0;
                 }
@@ -3912,9 +3852,13 @@ int config_parse_memory_limit(
                 c->memory_max = bytes;
         else if (streq(lvalue, "MemorySwapMax"))
                 c->memory_swap_max = bytes;
-        else if (streq(lvalue, "MemoryLimit"))
+        else if (streq(lvalue, "MemoryZSwapMax"))
+                c->memory_zswap_max = bytes;
+        else if (streq(lvalue, "MemoryLimit")) {
+                log_syntax(unit, LOG_WARNING, filename, line, 0,
+                           "Unit uses MemoryLimit=; please use MemoryMax= instead. Support for MemoryLimit= will be removed soon.");
                 c->memory_limit = bytes;
-        else
+        else
                 return -EINVAL;
 
         return 0;
@@ -4193,13 +4137,12 @@ int config_parse_io_device_weight(
         _cleanup_free_ char *path = NULL, *resolved = NULL;
         CGroupIODeviceWeight *w;
         CGroupContext *c = data;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         uint64_t u;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
 
         if (isempty(rvalue)) {
                 while (c->io_device_weights)
@@ -4267,13 +4210,12 @@ int config_parse_io_device_latency(
         _cleanup_free_ char *path = NULL, *resolved = NULL;
         CGroupIODeviceLatency *l;
         CGroupContext *c = data;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         usec_t usec;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
 
         if (isempty(rvalue)) {
                 while (c->io_device_latencies)
@@ -4340,13 +4282,12 @@ int config_parse_io_limit(
         CGroupIODeviceLimit *l = NULL;
         CGroupContext *c = data;
         CGroupIOLimitType type;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         uint64_t num;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
 
         type = cgroup_io_limit_type_from_string(lvalue);
         assert(type >= 0);
@@ -4432,13 +4373,16 @@ int config_parse_blockio_device_weight(
         _cleanup_free_ char *path = NULL, *resolved = NULL;
         CGroupBlockIODeviceWeight *w;
         CGroupContext *c = data;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         uint64_t u;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "Unit uses %s=; please use IO*= settings instead. Support for %s= will be removed soon.",
+                   lvalue, lvalue);
 
         if (isempty(rvalue)) {
                 while (c->blockio_device_weights)
@@ -4506,14 +4450,17 @@ int config_parse_blockio_bandwidth(
         _cleanup_free_ char *path = NULL, *resolved = NULL;
         CGroupBlockIODeviceBandwidth *b = NULL;
         CGroupContext *c = data;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         uint64_t bytes;
         bool read;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
+
+        log_syntax(unit, LOG_WARNING, filename, line, 0,
+                   "Unit uses %s=; please use IO*= settings instead. Support for %s= will be removed soon.",
+                   lvalue, lvalue);
 
         read = streq("BlockIOReadBandwidth", lvalue);
 
@@ -4625,14 +4572,13 @@ int config_parse_exec_directories(
                 void *data,
                 void *userdata) {
 
-        ExecDirectory *ed = data;
+        ExecDirectory *ed = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -4685,10 +4631,8 @@ int config_parse_exec_directories(
 
                 /* For State and Runtime directories we support an optional destination parameter, which
                  * will be used to create a symlink to the source. */
-                _cleanup_strv_free_ char **symlinks = NULL;
+                _cleanup_free_ char *dresolved = NULL;
                 if (!isempty(dest)) {
-                        _cleanup_free_ char *dresolved = NULL;
-
                         if (streq(lvalue, "ConfigurationDirectory")) {
                                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                                            "Destination parameter is not supported for ConfigurationDirectory, ignoring: %s", tuple);
@@ -4705,13 +4649,9 @@ int config_parse_exec_directories(
                         r = path_simplify_and_warn(dresolved, PATH_CHECK_RELATIVE, unit, filename, line, lvalue);
                         if (r < 0)
                                 continue;
-
-                        r = strv_consume(&symlinks, TAKE_PTR(dresolved));
-                        if (r < 0)
-                                return log_oom();
                 }
 
-                r = exec_directory_add(&ed->items, &ed->n_items, sresolved, symlinks);
+                r = exec_directory_add(ed, sresolved, dresolved);
                 if (r < 0)
                         return log_oom();
         }
@@ -4731,18 +4671,16 @@ int config_parse_set_credential(
 
         _cleanup_free_ char *word = NULL, *k = NULL;
         _cleanup_free_ void *d = NULL;
-        ExecContext *context = data;
+        ExecContext *context = ASSERT_PTR(data);
         ExecSetCredential *old;
         Unit *u = userdata;
         bool encrypted = ltype;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         size_t size;
         int r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
-        assert(context);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -4840,7 +4778,7 @@ int config_parse_load_credential(
                 void *userdata) {
 
         _cleanup_free_ char *word = NULL, *k = NULL, *q = NULL;
-        ExecContext *context = data;
+        ExecContext *context = ASSERT_PTR(data);
         ExecLoadCredential *old;
         bool encrypted = ltype;
         Unit *u = userdata;
@@ -4850,7 +4788,6 @@ int config_parse_load_credential(
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(context);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -4939,13 +4876,12 @@ int config_parse_set_status(
                 void *data,
                 void *userdata) {
 
-        ExitStatusSet *status_set = data;
+        ExitStatusSet *status_set = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(status_set);
 
         /* Empty assignment resets the list */
         if (isempty(rvalue)) {
@@ -5005,13 +4941,12 @@ int config_parse_namespace_path_strv(
                 void *userdata) {
 
         const Unit *u = userdata;
-        char*** sv = data;
+        char*** sv = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -5081,13 +5016,12 @@ int config_parse_temporary_filesystems(
                 void *userdata) {
 
         const Unit *u = userdata;
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -5152,14 +5086,13 @@ int config_parse_bind_paths(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -5280,14 +5213,13 @@ int config_parse_mount_images(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -5440,14 +5372,13 @@ int config_parse_extension_images(
                 void *data,
                 void *userdata) {
 
-        ExecContext *c = data;
+        ExecContext *c = ASSERT_PTR(data);
         const Unit *u = userdata;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -5581,14 +5512,13 @@ int config_parse_job_timeout_sec(
                 void *data,
                 void *userdata) {
 
-        Unit *u = data;
+        Unit *u = ASSERT_PTR(data);
         usec_t usec;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = parse_sec_fix_0(rvalue, &usec);
         if (r < 0) {
@@ -5620,14 +5550,13 @@ int config_parse_job_running_timeout_sec(
                 void *data,
                 void *userdata) {
 
-        Unit *u = data;
+        Unit *u = ASSERT_PTR(data);
         usec_t usec;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         r = parse_sec_fix_0(rvalue, &usec);
         if (r < 0) {
@@ -5653,36 +5582,26 @@ int config_parse_emergency_action(
                 void *data,
                 void *userdata) {
 
-        Manager *m = NULL;
-        EmergencyAction *x = data;
+        EmergencyAction *x = ASSERT_PTR(data);
+        bool is_system;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
+        /* If we have a unit determine the scope based on it */
         if (unit)
-                m = ((Unit*) userdata)->manager;
+                is_system = MANAGER_IS_SYSTEM(((Unit*) ASSERT_PTR(userdata))->manager);
         else
-                m = data;
+                is_system = ltype; /* otherwise, assume the scope is passed in via ltype */
 
-        r = parse_emergency_action(rvalue, MANAGER_IS_SYSTEM(m), x);
+        r = parse_emergency_action(rvalue, is_system, x);
         if (r < 0) {
-                if (r == -EOPNOTSUPP && MANAGER_IS_USER(m)) {
-                        /* Compat mode: remove for systemd 241. */
-
-                        log_syntax(unit, LOG_INFO, filename, line, r,
-                                   "%s= in user mode specified as \"%s\", using \"exit-force\" instead.",
-                                   lvalue, rvalue);
-                        *x = EMERGENCY_ACTION_EXIT_FORCE;
-                        return 0;
-                }
-
                 if (r == -EOPNOTSUPP)
                         log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "%s= specified as %s mode action, ignoring: %s",
-                                   lvalue, MANAGER_IS_SYSTEM(m) ? "user" : "system", rvalue);
+                                   lvalue, is_system ? "user" : "system", rvalue);
                 else
                         log_syntax(unit, LOG_WARNING, filename, line, r,
                                    "Failed to parse %s=, ignoring: %s", lvalue, rvalue);
@@ -5705,14 +5624,13 @@ int config_parse_pid_file(
                 void *userdata) {
 
         _cleanup_free_ char *k = NULL, *n = NULL;
-        const Unit *u = userdata;
+        const Unit *u = ASSERT_PTR(userdata);
         char **s = data;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(u);
 
         if (isempty(rvalue)) {
                 /* An empty assignment removes already set value. */
@@ -5828,13 +5746,12 @@ int config_parse_ip_filter_bpf_progs(
 
         _cleanup_free_ char *resolved = NULL;
         const Unit *u = userdata;
-        char ***paths = data;
+        char ***paths = ASSERT_PTR(data);
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(paths);
 
         if (isempty(rvalue)) {
                 *paths = strv_free(*paths);
@@ -5887,13 +5804,12 @@ int config_parse_bpf_foreign_program(
                 void *userdata) {
         _cleanup_free_ char *resolved = NULL, *word = NULL;
         CGroupContext *c = data;
-        const char *p = rvalue;
+        const char *p = ASSERT_PTR(rvalue);
         Unit *u = userdata;
         int attach_type, r;
 
         assert(filename);
         assert(lvalue);
-        assert(rvalue);
 
         if (isempty(rvalue)) {
                 while (c->bpf_foreign_programs)
@@ -5993,14 +5909,13 @@ int config_parse_restrict_network_interfaces(
                 const char *rvalue,
                 void *data,
                 void *userdata) {
-        CGroupContext *c = data;
+        CGroupContext *c = ASSERT_PTR(data);
         bool is_allow_rule = true;
         int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (isempty(rvalue)) {
                 /* Empty assignment resets the list */
@@ -6096,6 +6011,7 @@ int unit_load_fragment(Unit *u) {
         assert(u->id);
 
         if (u->transient) {
+                u->access_selinux_context = mfree(u->access_selinux_context);
                 u->load_state = UNIT_LOADED;
                 return 0;
         }
@@ -6141,7 +6057,24 @@ int unit_load_fragment(Unit *u) {
 
                         u->load_state = u->perpetual ? UNIT_LOADED : UNIT_MASKED; /* don't allow perpetual units to ever be masked */
                         u->fragment_mtime = 0;
+                        u->access_selinux_context = mfree(u->access_selinux_context);
                 } else {
+#if HAVE_SELINUX
+                        if (mac_selinux_use()) {
+                                _cleanup_freecon_ char *selcon = NULL;
+
+                                /* Cache the SELinux context of the unit file here. We'll make use of when checking access permissions to loaded units */
+                                r = fgetfilecon_raw(fileno(f), &selcon);
+                                if (r < 0)
+                                        log_unit_warning_errno(u, r, "Failed to read SELinux context of '%s', ignoring: %m", fragment);
+
+                                r = free_and_strdup(&u->access_selinux_context, selcon);
+                                if (r < 0)
+                                        return r;
+                        } else
+#endif
+                                u->access_selinux_context = mfree(u->access_selinux_context);
+
                         u->load_state = UNIT_LOADED;
                         u->fragment_mtime = timespec_load(&st.st_mtim);
 
@@ -6267,6 +6200,7 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_restrict_filesystems,  "FILESYSTEMS"  },
                 { config_parse_cpu_shares,            "SHARES" },
                 { config_parse_cg_weight,             "WEIGHT" },
+                { config_parse_cg_cpu_weight,         "CPUWEIGHT" },
                 { config_parse_memory_limit,          "LIMIT" },
                 { config_parse_device_allow,          "DEVICE" },
                 { config_parse_device_policy,         "POLICY" },
@@ -6284,10 +6218,10 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_job_mode,              "MODE" },
                 { config_parse_job_mode_isolate,      "BOOLEAN" },
                 { config_parse_personality,           "PERSONALITY" },
+                { config_parse_log_filter_patterns,   "REGEX" },
         };
 
         const char *prev = NULL;
-        const char *i;
 
         assert(f);
 
@@ -6340,9 +6274,7 @@ int config_parse_cpu_affinity2(
                 void *data,
                 void *userdata) {
 
-        CPUSet *affinity = data;
-
-        assert(affinity);
+        CPUSet *affinity = ASSERT_PTR(data);
 
         (void) parse_cpu_set_extend(rvalue, affinity, true, unit, filename, line, lvalue);
 
@@ -6362,12 +6294,11 @@ int config_parse_show_status(
                 void *userdata) {
 
         int k;
-        ShowStatus *b = data;
+        ShowStatus *b = ASSERT_PTR(data);
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         k = parse_show_status(rvalue, b);
         if (k < 0)
@@ -6388,13 +6319,12 @@ int config_parse_output_restricted(
                 void *data,
                 void *userdata) {
 
-        ExecOutput t, *eo = data;
+        ExecOutput t, *eo = ASSERT_PTR(data);
         bool obsolete = false;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
-        assert(data);
 
         if (streq(rvalue, "syslog")) {
                 t = EXEC_OUTPUT_JOURNAL;
@@ -6462,10 +6392,9 @@ int config_parse_swap_priority(
                 void *data,
                 void *userdata) {
 
-        Swap *s = userdata;
+        Swap *s = ASSERT_PTR(userdata);
         int r, priority;
 
-        assert(s);
         assert(filename);
         assert(lvalue);
         assert(rvalue);
@@ -6554,3 +6483,89 @@ int config_parse_tty_size(
 
         return config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
 }
+
+int config_parse_log_filter_patterns(
+                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) {
+
+        ExecContext *c = ASSERT_PTR(data);
+        const char *pattern = ASSERT_PTR(rvalue);
+        bool is_allowlist = true;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+
+        if (isempty(pattern)) {
+                /* Empty assignment resets the lists. */
+                c->log_filter_allowed_patterns = set_free(c->log_filter_allowed_patterns);
+                c->log_filter_denied_patterns = set_free(c->log_filter_denied_patterns);
+                return 0;
+        }
+
+        if (pattern[0] == '~') {
+                is_allowlist = false;
+                pattern++;
+                if (isempty(pattern))
+                        /* LogFilterPatterns=~ is not considered a valid pattern. */
+                        return log_syntax(unit, LOG_WARNING, filename, line, 0,
+                                          "Regex pattern invalid, ignoring: %s=%s", lvalue, rvalue);
+        }
+
+        if (pattern_compile_and_log(pattern, 0, NULL) < 0)
+                return 0;
+
+        r = set_put_strdup(is_allowlist ? &c->log_filter_allowed_patterns : &c->log_filter_denied_patterns,
+                           pattern);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r,
+                           "Failed to store log filtering pattern, ignoring: %s=%s", lvalue, rvalue);
+                return 0;
+        }
+
+        return 0;
+}
+
+int config_parse_open_file(
+                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) {
+
+        _cleanup_(open_file_freep) OpenFile *of = NULL;
+        OpenFile **head = ASSERT_PTR(data);
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                open_file_free_many(head);
+                return 0;
+        }
+
+        r = open_file_parse(rvalue, &of);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse OpenFile= setting, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        LIST_APPEND(open_files, *head, TAKE_PTR(of));
+
+        return 0;
+}