#1 Resync c8s-sig-hyperscale branch
Merged 2 years ago by dcavalca. Opened 2 years ago by dcavalca.
rpms/ dcavalca/systemd c8s-sig-hyperscale  into  c8s-sig-hyperscale

Disable legacy iptables support
Davide Cavalca • 2 years ago  
revert to previous python build deps
Anita Zhang • 2 years ago  
minor correction to changelog
Anita Zhang • 2 years ago  
249.2-1.1: new release
Anita Zhang • 2 years ago  
Add missing SELinux rules for 248
Davide Cavalca • 2 years ago  
248.2: new release
Anita Zhang • 2 years ago  
new release 247.3-1
Anita Zhang • 3 years ago  
file added
+5
@@ -0,0 +1,5 @@ 

+ BUILD/

+ BUILDROOT/

+ RPMS/

+ SOURCES/*.tar.gz

+ SRPMS/

file added
+1
@@ -0,0 +1,1 @@ 

+ 5e3b9df64a15cb3b446c0e74556ea9020ce50b8b SOURCES/systemd-249.4.tar.gz

@@ -1,42 +0,0 @@ 

- From b177b0ef92d226a9f303aecbff0cf2e7293667b3 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Sat, 8 Aug 2020 09:21:37 +0200

- Subject: [PATCH] Do not assert in test_add_acls_for_user()

- 

- This is failing on s390x with:

- /* test_add_acls_for_user */

- add_acls_for_user(3, 1000): Invalid argument

- Assertion 'r >= 0' failed at src/test/test-acl-util.c:46, function test_add_acls_for_user(). Aborting.

- ---

-  src/test/test-acl-util.c | 4 ----

-  1 file changed, 4 deletions(-)

- 

- diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c

- index 9f0e594e67..a91d64ab0c 100644

- --- a/src/test/test-acl-util.c

- +++ b/src/test/test-acl-util.c

- @@ -43,24 +43,20 @@ static void test_add_acls_for_user(void) {

-  

-          r = add_acls_for_user(fd, uid);

-          log_info_errno(r, "add_acls_for_user(%d, "UID_FMT"): %m", fd, uid);

- -        assert_se(r >= 0);

-  

-          cmd = strjoina("ls -l ", fn);

-          assert_se(system(cmd) == 0);

-  

-          cmd = strjoina("getfacl -p ", fn);

- -        assert_se(system(cmd) == 0);

-  

-          /* set the acls again */

-  

-          r = add_acls_for_user(fd, uid);

- -        assert_se(r >= 0);

-  

-          cmd = strjoina("ls -l ", fn);

-          assert_se(system(cmd) == 0);

-  

-          cmd = strjoina("getfacl -p ", fn);

- -        assert_se(system(cmd) == 0);

-  

-          unlink(fn);

-  }

@@ -1,30 +0,0 @@ 

- From a73d30081a13eaeffce87f997726a179ec44d817 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Fri, 31 Jul 2020 10:50:37 +0200

- Subject: [PATCH 1/2] Revert "test-path: increase timeout"

- 

- This partially reverts commit 500727c220354b81b68ed6667d9a6f0fafe3ba19.

- 

- I was confused by the error message: the test says it timed out, but that's

- because it's waiting for a failed unit to come back to life. There is no actual

- timeout.

- 

- So let's keep the minor refactoring that was done, but revert to the old short

- timeout.

- ---

-  src/test/test-path.c | 2 +-

-  1 file changed, 1 insertion(+), 1 deletion(-)

- 

- diff --git a/src/test/test-path.c b/src/test/test-path.c

- index 1075f31bc6..63b709c8da 100644

- --- a/src/test/test-path.c

- +++ b/src/test/test-path.c

- @@ -82,7 +82,7 @@ static void check_states(Manager *m, Path *path, Service *service, PathState pat

-          assert_se(m);

-          assert_se(service);

-  

- -        usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC;

- +        usec_t end = now(CLOCK_MONOTONIC) + 2 * USEC_PER_SEC;

-  

-          while (path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS ||

-                 path->state != path_state || service->state != service_state) {

@@ -1,427 +0,0 @@ 

- From a1ff72565c2f12b644a081ebbe3492f93ceb3bd5 Mon Sep 17 00:00:00 2001

- From: Chris Down <chris@chrisdown.name>

- Date: Thu, 29 Oct 2020 12:03:52 +0000

- Subject: [PATCH 1/3] bpf: pid1: Pin reference to BPF programs for

-  post-coldplug

- MIME-Version: 1.0

- Content-Type: text/plain; charset=UTF-8

- Content-Transfer-Encoding: 8bit

- 

- During `daemon-reload` and `daemon-reexec`, we detach and reattach all

- BPF programs attached to cgroups. This, however, poses a real practical

- problem for DevicePolicy (and some other settings using BPF): it

- presents a period of time where the old device filtering BPF program has

- been unloaded, but the new one has not been loaded yet.

- 

- Since the filtering is at open() time, it has become apparent that that

- there's a non-trivial period where applications inside that ostensibly

- filtered cgroup can grab any device -- and often do so -- and then

- retain access to that device even after the reload is over. Due to the

- file continuing to be available after the initial open(), this issue is

- particularly visible for DevicePolicy={strict,closed}, however it also

- applies to other BPF programs we install.

- 

- In particular, for BPF ingress/egress filtering this may have more

- concerning implications: network traffic which is supposed to be

- filtered will -- for a very brief period of time -- not be filtered or

- subject to any restrictions imposed by BPF.

- 

- These BPF programs are fundamentally attached to a cgroup lifetime, not

- our unit lifetime, so it's enough to pin these programs by taking a

- reference to affected BPF programs before reload/reexec. We can then

- serialise the program's kernel-facing FD and cgroup attachment FD for

- the new daemon, and have the daemon on the other side unpin the programs

- after it's finished with coldplug.

- 

- That means that, for example, the BPF program lifecycle during

- daemon-reload or daemon-reexec changes from this:

- 

-     manager_clear_jobs_and_units

-                  │

-           ╔══════╪═════════╤═══════╗

-           ║ prog │ no prog │ prog' ║

-           ╚══════╧═════════╪═══════╝

-                            │

-                     manager_coldplug

- 

- to this:

- 

-     manager_clear_jobs_and_units         manager_dispatch_cgroup_realize_queue

-                  │                                       │

-           ╔══════╪═══════════════╤═══════════════════════╪═══════╗

-           ║ prog │ prog (orphan) │ prog (orphan) + prog' │ prog' ║

-           ╚══════╧═══════════════╪═══════════════════════╧═══════╝

-                                  │

-                           manager_coldplug

- 

- For daemon-reexec the semantics are mostly the same, but the point at

- which the program becomes orphan is tied to the process lifecycle

- instead.

- 

- None of the BPF programs we install require exclusive access, so having

- multiple instances of them running at the same time is fine. Custom

- programs, of course, are unknown, but it's hard to imagine legitimate

- cases which should be affected, whereas the benefits of this "overlap"

- approach with reference pinning is immediately tangible.

- 

- [keszybz: use _cleanup_ for unpin, use FOREACH_POINTER]

- ---

-  src/core/bpf-firewall.c  |   9 +--

-  src/core/main.c          |   9 +++

-  src/core/manager.c       | 163 ++++++++++++++++++++++++++++++++++++++-

-  src/core/manager.h       |   6 ++

-  src/shared/bpf-program.c |  10 +++

-  src/shared/bpf-program.h |   1 +

-  6 files changed, 191 insertions(+), 7 deletions(-)

- 

- diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c

- index bceb049b58..e3089ff6f4 100644

- --- a/src/core/bpf-firewall.c

- +++ b/src/core/bpf-firewall.c

- @@ -703,8 +703,7 @@ int bpf_firewall_install(Unit *u) {

-          if (r < 0)

-                  return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m");

-  

- -        flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI &&

- -                 (u->type == UNIT_SLICE || unit_cgroup_delegate(u))) ? BPF_F_ALLOW_MULTI : 0;

- +        flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI) ? BPF_F_ALLOW_MULTI : 0;

-  

-          /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program, to

-           * minimize the time window when we don't account for IP traffic. */

- @@ -712,8 +711,7 @@ int bpf_firewall_install(Unit *u) {

-          u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed);

-  

-          if (u->ip_bpf_egress) {

- -                r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path,

- -                                              flags | (set_isempty(u->ip_bpf_custom_egress) ? 0 : BPF_F_ALLOW_MULTI));

- +                r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags);

-                  if (r < 0)

-                          return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path);

-  

- @@ -722,8 +720,7 @@ int bpf_firewall_install(Unit *u) {

-          }

-  

-          if (u->ip_bpf_ingress) {

- -                r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path,

- -                                              flags | (set_isempty(u->ip_bpf_custom_ingress) ? 0 : BPF_F_ALLOW_MULTI));

- +                r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags);

-                  if (r < 0)

-                          return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path);

-  

- diff --git a/src/core/main.c b/src/core/main.c

- index 4a376976e9..9873f35f5e 100644

- --- a/src/core/main.c

- +++ b/src/core/main.c

- @@ -1144,6 +1144,14 @@ static int prepare_reexecute(

-          if (!fds)

-                  return log_oom();

-  

- +        /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF

- +         * program is active during task execution within a cgroup. This would be bad since this may have

- +         * security or reliability implications: devices we should filter won't be filtered, network activity

- +         * we should filter won't be filtered, etc. We pin all the existing devices by bumping their

- +         * refcount, and then storing them to later have it decremented. */

- +        _cleanup_(manager_unpin_all_cgroup_bpf_programsp) Manager *m_unpin =

- +                manager_pin_all_cgroup_bpf_programs(m);

- +

-          r = manager_serialize(m, f, fds, switching_root);

-          if (r < 0)

-                  return r;

- @@ -1159,6 +1167,7 @@ static int prepare_reexecute(

-          if (r < 0)

-                  return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m");

-  

- +        TAKE_PTR(m_unpin);

-          *ret_f = TAKE_PTR(f);

-          *ret_fds = TAKE_PTR(fds);

-  

- diff --git a/src/core/manager.c b/src/core/manager.c

- index 41e0d73736..1ce0e05706 100644

- --- a/src/core/manager.c

- +++ b/src/core/manager.c

- @@ -64,6 +64,7 @@

-  #include "rlimit-util.h"

-  #include "rm-rf.h"

-  #include "serialize.h"

- +#include "set.h"

-  #include "signal-util.h"

-  #include "socket-util.h"

-  #include "special.h"

- @@ -3210,6 +3211,79 @@ static void manager_serialize_gid_refs(Manager *m, FILE *f) {

-          manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid");

-  }

-  

- +static int serialize_limbo_bpf_program(FILE *f, FDSet *fds, BPFProgram *p) {

- +        int copy;

- +        _cleanup_free_ char *ap = NULL;

- +

- +        /* We don't actually need the instructions or other data, since this is only used on the other side

- +         * for BPF limbo, which just requires the program type, cgroup path, and kernel-facing BPF file

- +         * descriptor. We don't even need to know what unit or directive it's attached to, since we're just

- +         * going to expire it after coldplug. */

- +

- +        assert(f);

- +        assert(p);

- +

- +        /* If the program isn't attached to the kernel yet, there's no reason to serialise it for limbo. Just

- +         * let it be skeletonized and then coldplug can do the work on the other side if it's still

- +         * necessary. */

- +        if (p->kernel_fd < 0 || !p->attached_path)

- +                return -ENOTCONN;

- +

- +        copy = fdset_put_dup(fds, p->kernel_fd);

- +        if (copy < 0)

- +                return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");

- +

- +        /* Otherwise, on daemon-reload, we'd remain pinned. */

- +        safe_close(p->kernel_fd);

- +

- +        ap = cescape(p->attached_path);

- +        if (!ap)

- +                return log_oom();

- +

- +        return serialize_item_format(f, "bpf-limbo", "%i %i %i \"%s\"",

- +                                     copy, p->prog_type, p->attached_type, ap);

- +}

- +

- +static void deserialize_limbo_bpf_program(Manager *m, FDSet *fds, const char *value) {

- +        _cleanup_free_ char *raw_fd = NULL, *raw_pt = NULL, *raw_at = NULL, *cgpath = NULL;

- +        int fd, r, prog_type, attached_type;

- +

- +        assert(m);

- +        assert(value);

- +

- +        r = extract_first_word(&value, &raw_fd, NULL, 0);

- +        if (r <= 0 || safe_atoi(raw_fd, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))

- +                return (void) log_error("Failed to parse bpf-limbo FD: %s", value);

- +

- +        r = extract_first_word(&value, &raw_pt, NULL, 0);

- +        if (r <= 0 || safe_atoi(raw_pt, &prog_type) < 0)

- +                return (void) log_error("Failed to parse bpf-limbo program type: %s", value);

- +

- +        r = extract_first_word(&value, &raw_at, NULL, 0);

- +        if (r <= 0 || safe_atoi(raw_at, &attached_type) < 0)

- +                return (void) log_error("Failed to parse bpf-limbo attached type: %s", value);

- +

- +        r = extract_first_word(&value, &cgpath, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE);

- +        if (r <= 0)

- +                return (void) log_error("Failed to parse attached path for BPF limbo FD %s", value);

- +

- +        _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL;

- +        r = bpf_program_new(prog_type, &p);

- +        if (r < 0)

- +                return (void) log_error_errno(r, "Failed to create BPF limbo program: %m");

- +

- +        /* Just enough to free it when the time is right, this does not have enough information be used as a

- +         * real BPFProgram. */

- +        p->attached_type = attached_type;

- +        p->kernel_fd = fdset_remove(fds, fd);

- +        p->attached_path = TAKE_PTR(cgpath);

- +

- +        r = set_ensure_put(&m->bpf_limbo_progs, NULL, p);

- +        if (r < 0)

- +                return (void) log_error_errno(r, "Failed to register BPF limbo program for FD %s: %m", value);

- +        TAKE_PTR(p);

- +}

- +

-  int manager_serialize(

-                  Manager *m,

-                  FILE *f,

- @@ -3221,6 +3295,7 @@ int manager_serialize(

-          Iterator i;

-          Unit *u;

-          int r;

- +        BPFProgram *p;

-  

-          assert(m);

-          assert(f);

- @@ -3265,6 +3340,9 @@ int manager_serialize(

-                  (void) serialize_dual_timestamp(f, joined, m->timestamps + q);

-          }

-  

- +        SET_FOREACH(p, m->bpf_limbo_progs, i)

- +                (void) serialize_limbo_bpf_program(f, fds, p);

- +

-          if (!switching_root)

-                  (void) serialize_strv(f, "env", m->client_environment);

-  

- @@ -3543,7 +3621,10 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {

-                          else

-                                  m->n_failed_jobs += n;

-  

- -                } else if ((val = startswith(l, "taint-usr="))) {

- +                } else if ((val = startswith(l, "bpf-limbo=")))

- +                        deserialize_limbo_bpf_program(m, fds, val);

- +

- +                else if ((val = startswith(l, "taint-usr="))) {

-                          int b;

-  

-                          b = parse_boolean(val);

- @@ -3719,6 +3800,67 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {

-          return manager_deserialize_units(m, f, fds);

-  }

-  

- +Manager* manager_pin_all_cgroup_bpf_programs(Manager *m) {

- +        int r;

- +        Unit *u;

- +        Iterator ih, is;

- +

- +        assert(m);

- +

- +        HASHMAP_FOREACH(u, m->units, ih) {

- +                BPFProgram *p;

- +

- +                FOREACH_POINTER(p,

- +                                u->bpf_device_control_installed,

- +                                u->ip_bpf_ingress,

- +                                u->ip_bpf_ingress_installed,

- +                                u->ip_bpf_egress,

- +                                u->ip_bpf_egress_installed)

- +                        if (p) {

- +                                r = set_ensure_put(&m->bpf_limbo_progs, NULL, p);

- +                                if (r < 0) {

- +                                        log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m");

- +                                        continue;

- +                                }

- +

- +                                bpf_program_ref(p);

- +                        }

- +

- +                Set *s;

- +                FOREACH_POINTER(s,

- +                                u->ip_bpf_custom_ingress,

- +                                u->ip_bpf_custom_ingress_installed,

- +                                u->ip_bpf_custom_egress,

- +                                u->ip_bpf_custom_egress_installed)

- +                        SET_FOREACH(p, s, is) {

- +                                r = set_ensure_put(&m->bpf_limbo_progs, NULL, p);

- +                                if (r < 0) {

- +                                        log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m");

- +                                        continue;

- +                                }

- +

- +                                bpf_program_ref(p);

- +                        }

- +        }

- +

- +        log_debug("Pinned %d BPF programs", set_size(m->bpf_limbo_progs));

- +

- +        return m;

- +}

- +

- +static void manager_skeletonize_all_cgroup_bpf_programs(Manager *m) {

- +        BPFProgram *p;

- +        Iterator i;

- +

- +        SET_FOREACH(p, m->bpf_limbo_progs, i)

- +                bpf_program_skeletonize(p);

- +}

- +

- +void manager_unpin_all_cgroup_bpf_programs(Manager *m) {

- +        log_debug("Unpinning %d BPF programs", set_size(m->bpf_limbo_progs));

- +        set_clear_with_destructor(m->bpf_limbo_progs, bpf_program_unref);

- +}

- +

-  int manager_reload(Manager *m) {

-          _cleanup_(manager_reloading_stopp) Manager *reloading = NULL;

-          _cleanup_fdset_free_ FDSet *fds = NULL;

- @@ -3738,6 +3880,13 @@ int manager_reload(Manager *m) {

-          /* We are officially in reload mode from here on. */

-          reloading = manager_reloading_start(m);

-  

- +        /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF

- +         * program is active during task execution within a cgroup. This would be bad since this may have

- +         * security or reliability implications: devices we should filter won't be filtered, network activity

- +         * we should filter won't be filtered, etc. We pin all the existing devices by bumping their

- +         * refcount, and then storing them to later have it decremented. */

- +        (void) manager_pin_all_cgroup_bpf_programs(m);

- +

-          r = manager_serialize(m, f, fds, false);

-          if (r < 0)

-                  return r;

- @@ -3762,6 +3911,12 @@ int manager_reload(Manager *m) {

-          m->uid_refs = hashmap_free(m->uid_refs);

-          m->gid_refs = hashmap_free(m->gid_refs);

-  

- +        /* The only canonical reference left to the dynamically allocated parts of these BPF programs is

- +         * going to be on the other side of manager_deserialize, so the freeable parts can now be freed. The

- +         * program itself will be detached as part of manager_vacuum. */

- +        manager_skeletonize_all_cgroup_bpf_programs(m);

- +        m->bpf_limbo_progs = set_free(m->bpf_limbo_progs);

- +

-          r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL);

-          if (r < 0)

-                  log_warning_errno(r, "Failed to initialize path lookup table, ignoring: %m");

- @@ -4700,6 +4855,12 @@ static void manager_vacuum(Manager *m) {

-  

-          /* Release any runtimes no longer referenced */

-          exec_runtime_vacuum(m);

- +

- +        /* Release any outmoded BPF programs that were deserialized from the previous manager, since new ones

- +         * should be in action now. We first need to make sure all entries in the cgroup realize queue are

- +         * complete, otherwise BPF firewalls/etc may not have been set up yet. */

- +        (void) manager_dispatch_cgroup_realize_queue(m);

- +        manager_unpin_all_cgroup_bpf_programs(m);

-  }

-  

-  int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) {

- diff --git a/src/core/manager.h b/src/core/manager.h

- index 81b0c13a95..6f8f8b04b4 100644

- --- a/src/core/manager.h

- +++ b/src/core/manager.h

- @@ -433,6 +433,8 @@ struct Manager {

-          bool honor_device_enumeration;

-  

-          VarlinkServer *varlink_server;

- +

- +        Set *bpf_limbo_progs;

-  };

-  

-  static inline usec_t manager_default_timeout_abort_usec(Manager *m) {

- @@ -474,6 +476,10 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode

-  int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs,  Job **ret);

-  int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e);

-  

- +Manager* manager_pin_all_cgroup_bpf_programs(Manager *m);

- +void manager_unpin_all_cgroup_bpf_programs(Manager *m);

- +DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unpin_all_cgroup_bpf_programs);

- +

-  void manager_dump_units(Manager *s, FILE *f, const char *prefix);

-  void manager_dump_jobs(Manager *s, FILE *f, const char *prefix);

-  void manager_dump(Manager *s, FILE *f, const char *prefix);

- diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c

- index e5c9df4004..cc479aa52e 100644

- --- a/src/shared/bpf-program.c

- +++ b/src/shared/bpf-program.c

- @@ -210,6 +210,16 @@ int bpf_program_cgroup_detach(BPFProgram *p) {

-          return 0;

-  }

-  

- +void bpf_program_skeletonize(BPFProgram *p) {

- +        assert(p);

- +

- +        /* Called shortly after serialization. From this point on, we are frozen for serialization and entry

- +         * into BPF limbo, so we should proactively free our instructions and attached path. However, we

- +         * shouldn't detach the program or close the kernel FD -- we need those on the other side. */

- +        free(p->instructions);

- +        free(p->attached_path);

- +}

- +

-  int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) {

-          union bpf_attr attr = {

-                  .map_type = type,

- diff --git a/src/shared/bpf-program.h b/src/shared/bpf-program.h

- index a21589eb1f..6ea5d9a57c 100644

- --- a/src/shared/bpf-program.h

- +++ b/src/shared/bpf-program.h

- @@ -28,6 +28,7 @@ struct BPFProgram {

-  int bpf_program_new(uint32_t prog_type, BPFProgram **ret);

-  BPFProgram *bpf_program_unref(BPFProgram *p);

-  BPFProgram *bpf_program_ref(BPFProgram *p);

- +void bpf_program_skeletonize(BPFProgram *p);

-  

-  int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count);

-  int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size);

- -- 

- 2.24.1

- 

@@ -0,0 +1,257 @@ 

+ From d4bd8777a483ea834e687c1ee35dee32efe6e49f Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Wed, 7 Jul 2021 14:02:36 +0200

+ Subject: [PATCH 1/5] rpm: don't specify the full path for systemctl and other

+  commands

+ 

+ We can make things a bit simpler and more readable by not specifying the path.

+ Since we didn't specify the full path for all commands (including those invoked

+ recursively by anythign we invoke), this didn't really privide any security or

+ robustness benefits. I guess that full paths were used because this style of

+ rpm packagnig was popular in the past, with macros used for everything

+ possible, with special macros for common commands like %{__ln} and %{__mkdir}.

+ 

+ (cherry picked from commit 7d9ee15d0fc2af87481ee371b278dbe7e68165ef)

+ ---

+  src/rpm/macros.systemd.in      | 24 ++++++++++++------------

+  src/rpm/triggers.systemd.in    | 18 +++++++++---------

+  src/rpm/triggers.systemd.sh.in | 18 +++++++++---------

+  3 files changed, 30 insertions(+), 30 deletions(-)

+ 

+ diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in

+ index 3a0169a85f..3129ab2d61 100644

+ --- a/src/rpm/macros.systemd.in

+ +++ b/src/rpm/macros.systemd.in

+ @@ -46,9 +46,9 @@ OrderWithRequires(postun): systemd \

+  

+  %systemd_post() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \

+ -if [ $1 -eq 1 ] && [ -x %{_bindir}/systemctl ]; then \

+ +if [ $1 -eq 1 ] && command -v systemctl >/dev/null; then \

+      # Initial installation \

+ -    %{_bindir}/systemctl --no-reload preset %{?*} || : \

+ +    systemctl --no-reload preset %{?*} || : \

+  fi \

+  %{nil}

+  

+ @@ -56,21 +56,21 @@ fi \

+  

+  %systemd_preun() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \

+ -if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \

+ +if [ $1 -eq 0 ] && command -v systemctl >/dev/null; then \

+      # Package removal, not upgrade \

+      if [ -d /run/systemd/system ]; then \

+ -          %{_bindir}/systemctl --no-reload disable --now %{?*} || : \

+ +          systemctl --no-reload disable --now %{?*} || : \

+      else \

+ -          %{_bindir}/systemctl --no-reload disable %{?*} || : \

+ +          systemctl --no-reload disable %{?*} || : \

+      fi \

+  fi \

+  %{nil}

+  

+  %systemd_user_preun() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \

+ -if [ $1 -eq 0 ] && [ -x %{_bindir}/systemctl ]; then \

+ +if [ $1 -eq 0 ] && command -v systemctl >/dev/null; then \

+      # Package removal, not upgrade \

+ -    %{_bindir}/systemctl --global disable %{?*} || : \

+ +    systemctl --global disable %{?*} || : \

+  fi \

+  %{nil}

+  

+ @@ -84,10 +84,10 @@ fi \

+  

+  %systemd_postun_with_restart() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \

+ -if [ $1 -ge 1 ] && [ -x %{_bindir}/systemctl ]; then \

+ +if [ $1 -ge 1 ] && command -v systemctl >/dev/null; then \

+      # Package upgrade, not uninstall \

+      for unit in %{?*}; do \

+ -         %{_bindir}/systemctl set-property $unit Markers=+needs-restart || : \

+ +        systemctl set-property $unit Markers=+needs-restart || : \

+      done \

+  fi \

+  %{nil}

+ @@ -105,17 +105,17 @@ fi \

+  # Deprecated. Use %tmpfiles_create_package instead

+  %tmpfiles_create() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# tmpfiles_create}} \

+ -[ -x %{_bindir}/systemd-tmpfiles ] && %{_bindir}/systemd-tmpfiles --create %{?*} || : \

+ +command -v systemd-tmpfiles >/dev/null && systemd-tmpfiles --create %{?*} || : \

+  %{nil}

+  

+  # Deprecated. Use %sysusers_create_package instead

+  %sysusers_create() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# sysusers_create}} \

+ -[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers %{?*} || : \

+ +command -v systemd-sysusers >/dev/null && systemd-sysusers %{?*} || : \

+  %{nil}

+  

+  %sysusers_create_inline() \

+ -[ -x %{_bindir}/systemd-sysusers ] && %{_bindir}/systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \

+ +command -v systemd-sysusers >/dev/null && systemd-sysusers - <<SYSTEMD_INLINE_EOF || : \

+  %{?*} \

+  SYSTEMD_INLINE_EOF\

+  %{nil}

+ diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in

+ index b33d2212e8..247358008a 100644

+ --- a/src/rpm/triggers.systemd.in

+ +++ b/src/rpm/triggers.systemd.in

+ @@ -16,14 +16,14 @@

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))

+ +        assert(posix.execp("systemctl", "daemon-reload"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+  

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked"))

+ +        assert(posix.execp("systemctl", "reload-or-restart", "--marked"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -38,7 +38,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemctl", "daemon-reload"))

+ +        assert(posix.execp("systemctl", "daemon-reload"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -49,7 +49,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemctl", "reload-or-restart", "--marked"))

+ +        assert(posix.execp("systemctl", "reload-or-restart", "--marked"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -62,7 +62,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemd-sysusers"))

+ +        assert(posix.execp("systemd-sysusers"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -74,7 +74,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemd-hwdb", "update"))

+ +        assert(posix.execp("systemd-hwdb", "update"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -86,7 +86,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/journalctl", "--update-catalog"))

+ +        assert(posix.execp("journalctl", "--update-catalog"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -111,7 +111,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/systemd-tmpfiles", "--create"))

+ +        assert(posix.execp("systemd-tmpfiles", "--create"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ @@ -123,7 +123,7 @@ end

+  if posix.access("/run/systemd/system") then

+      pid = posix.fork()

+      if pid == 0 then

+ -        assert(posix.exec("%{_bindir}/udevadm", "control", "--reload"))

+ +        assert(posix.execp("udevadm", "control", "--reload"))

+      elseif pid > 0 then

+          posix.wait(pid)

+      end

+ diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in

+ index 22abad9812..1631be18c9 100644

+ --- a/src/rpm/triggers.systemd.sh.in

+ +++ b/src/rpm/triggers.systemd.sh.in

+ @@ -15,8 +15,8 @@

+  # installed, because other cases are covered by the *un scriptlets,

+  # so sometimes we will reload needlessly.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemctl daemon-reload || :

+ -  %{_bindir}/systemctl reload-or-restart --marked || :

+ +  systemctl daemon-reload || :

+ +  systemctl reload-or-restart --marked || :

+  fi

+  

+  %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+ @@ -26,13 +26,13 @@ fi

+  # have been installed, but before %postun scripts in packages get

+  # executed.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemctl daemon-reload || :

+ +  systemctl daemon-reload || :

+  fi

+  

+  %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  # We restart remaining services that should be restarted here.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemctl reload-or-restart --marked || :

+ +  systemctl reload-or-restart --marked || :

+  fi

+  

+  %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}

+ @@ -40,21 +40,21 @@ fi

+  # specified users automatically. The priority is set such that it

+  # will run before the tmpfiles file trigger.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemd-sysusers || :

+ +  systemd-sysusers || :

+  fi

+  

+  %transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}

+  # This script will automatically invoke hwdb update if files have been

+  # installed or updated in {{UDEV_HWDB_DIR}}.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemd-hwdb update || :

+ +  systemd-hwdb update || :

+  fi

+  

+  %transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}

+  # This script will automatically invoke journal catalog update if files

+  # have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/journalctl --update-catalog || :

+ +  journalctl --update-catalog || :

+  fi

+  

+  %transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}

+ @@ -71,14 +71,14 @@ fi

+  # tmpfiles automatically. The priority is set such that it will run

+  # after the sysusers file trigger, but before any other triggers.

+  if test -d "/run/systemd/system"; then

+ -  %{_bindir}/systemd-tmpfiles --create || :

+ +  systemd-tmpfiles --create || :

+  fi

+  

+  %transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}

+  # This script will automatically update udev with new rules if files

+  # have been installed or updated in {{UDEV_RULES_DIR}}.

+  if test -e /run/udev/control; then

+ -  %{_bindir}/udevadm control --reload || :

+ +  udevadm control --reload || :

+  fi

+  

+  %transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}

+ -- 

+ 2.31.1

+ 

@@ -0,0 +1,30 @@ 

+ From 0c21535392bf6296d213c35fd1a0b0bc89dbddb3 Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Wed, 31 Mar 2021 14:04:09 -0700

+ Subject: [PATCH] sysv-generator: downgrade log warning about autogenerated to

+  debug

+ 

+ ---

+  src/sysv-generator/sysv-generator.c | 6 +++---

+  1 file changed, 3 insertions(+), 3 deletions(-)

+ 

+ diff --git a/src/sysv-generator/sysv-generator.c b/src/sysv-generator/sysv-generator.c

+ index 8c7aef23c3..89599a69ee 100644

+ --- a/src/sysv-generator/sysv-generator.c

+ +++ b/src/sysv-generator/sysv-generator.c

+ @@ -786,9 +786,9 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {

+                          if (!fpath)

+                                  return log_oom();

+ 

+ -                        log_warning("SysV service '%s' lacks a native systemd unit file. "

+ -                                    "Automatically generating a unit file for compatibility. "

+ -                                    "Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath);

+ +                        log_debug("SysV service '%s' lacks a native systemd unit file. "

+ +                                  "Automatically generating a unit file for compatibility. "

+ +                                  "Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath);

+ 

+                          service = new(SysvStub, 1);

+                          if (!service)

+ --

+ 2.30.2

+ 

@@ -1,46 +0,0 @@ 

- From 8cad57ed62a642515670ba79dddb30193456e803 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Fri, 7 Aug 2020 18:54:37 +0200

- Subject: [PATCH] test-acl-util: output more debug info

- 

- For some reason this failed in koji build on s390x:

- --- command ---

- 16:12:46 PATH='/builddir/build/BUILD/systemd-stable-246.1/s390x-redhat-linux-gnu:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin' SYSTEMD_LANGUAGE_FALLBACK_MAP='/builddir/build/BUILD/systemd-stable-246.1/src/locale/language-fallback-map' SYSTEMD_KBD_MODEL_MAP='/builddir/build/BUILD/systemd-stable-246.1/src/locale/kbd-model-map' /builddir/build/BUILD/systemd-stable-246.1/s390x-redhat-linux-gnu/test-acl-util

- --- stdout ---

- -rw-r-----. 1 mockbuild mock 0 Aug  7 16:12 /tmp/test-empty.7RzmEc

- other::---

- --- stderr ---

- Assertion 'r >= 0' failed at src/test/test-acl-util.c:42, function test_add_acls_for_user(). Aborting.

- ---

-  src/test/test-acl-util.c | 4 ++++

-  1 file changed, 4 insertions(+)

- 

- diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c

- index df879747f5..9f0e594e67 100644

- --- a/src/test/test-acl-util.c

- +++ b/src/test/test-acl-util.c

- @@ -7,6 +7,7 @@

-  

-  #include "acl-util.h"

-  #include "fd-util.h"

- +#include "format-util.h"

-  #include "string-util.h"

-  #include "tmpfile-util.h"

-  #include "user-util.h"

- @@ -18,6 +19,8 @@ static void test_add_acls_for_user(void) {

-          uid_t uid;

-          int r;

-  

- +        log_info("/* %s */", __func__);

- +

-          fd = mkostemp_safe(fn);

-          assert_se(fd >= 0);

-  

- @@ -39,6 +42,7 @@ static void test_add_acls_for_user(void) {

-                  uid = getuid();

-  

-          r = add_acls_for_user(fd, uid);

- +        log_info_errno(r, "add_acls_for_user(%d, "UID_FMT"): %m", fd, uid);

-          assert_se(r >= 0);

-  

-          cmd = strjoina("ls -l ", fn);

@@ -1,124 +0,0 @@ 

- From b554f941a8f275124508794b0b83f0554c7b84dc Mon Sep 17 00:00:00 2001

- From: Anita Zhang <the.anitazha@gmail.com>

- Date: Thu, 22 Oct 2020 22:44:22 -0700

- Subject: [PATCH 2/3] core: clean up inactive/failed {service|scope}'s cgroups

-  when the last process exits

- 

- If processes remain in the unit's cgroup after the final SIGKILL is

- sent and the unit has exceeded stop timeout, don't release the unit's

- cgroup information. Pid1 will have failed to `rmdir` the cgroup path due

- to processes remaining in the cgroup and releasing would leave the cgroup

- path on the file system with no tracking for pid1 to clean it up.

- 

- Instead, keep the information around until the last process exits and pid1

- sends the cgroup empty notification. The service/scope can then prune

- the cgroup if the unit is inactive/failed.

- ---

-  src/core/cgroup.c  | 26 +++++++++++++++++++++++++-

-  src/core/cgroup.h  |  6 +++++-

-  src/core/scope.c   |  5 +++++

-  src/core/service.c |  7 +++++++

-  4 files changed, 42 insertions(+), 2 deletions(-)

- 

- diff --git a/src/core/cgroup.c b/src/core/cgroup.c

- index 031b28a684..bce5f44e78 100644

- --- a/src/core/cgroup.c

- +++ b/src/core/cgroup.c

- @@ -2414,6 +2414,29 @@ void unit_release_cgroup(Unit *u) {

-          }

-  }

-  

- +bool unit_maybe_release_cgroup(Unit *u) {

- +        int r;

- +

- +        assert(u);

- +

- +        if (!u->cgroup_path)

- +                return true;

- +

- +        /* Don't release the cgroup if there are still processes under it. If we get notified later when all the

- +         * processes exit (e.g. the processes were in D-state and exited after the unit was marked as failed)

- +         * we need the cgroup paths to continue to be tracked by the manager so they can be looked up and cleaned

- +         * up later. */

- +        r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);

- +        if (r < 0)

- +                log_unit_debug_errno(u, r, "Error checking if the cgroup is recursively empty, ignoring: %m");

- +        else if (r == 1) {

- +                unit_release_cgroup(u);

- +                return true;

- +        }

- +

- +        return false;

- +}

- +

-  void unit_prune_cgroup(Unit *u) {

-          int r;

-          bool is_root_slice;

- @@ -2441,7 +2464,8 @@ void unit_prune_cgroup(Unit *u) {

-          if (is_root_slice)

-                  return;

-  

- -        unit_release_cgroup(u);

- +        if (!unit_maybe_release_cgroup(u)) /* Returns true if the cgroup was released */

- +                return;

-  

-          u->cgroup_realized = false;

-          u->cgroup_realized_mask = 0;

- diff --git a/src/core/cgroup.h b/src/core/cgroup.h

- index 52d028e740..be6856c20c 100644

- --- a/src/core/cgroup.h

- +++ b/src/core/cgroup.h

- @@ -220,11 +220,15 @@ int unit_set_cgroup_path(Unit *u, const char *path);

-  int unit_pick_cgroup_path(Unit *u);

-  

-  int unit_realize_cgroup(Unit *u);

- -void unit_release_cgroup(Unit *u);

-  void unit_prune_cgroup(Unit *u);

-  int unit_watch_cgroup(Unit *u);

-  int unit_watch_cgroup_memory(Unit *u);

-  

- +void unit_release_cgroup(Unit *u);

- +/* Releases the cgroup only if it is recursively empty.

- + * Returns true if the cgroup was released, false otherwise. */

- +bool unit_maybe_release_cgroup(Unit *u);

- +

-  void unit_add_to_cgroup_empty_queue(Unit *u);

-  int unit_check_oom(Unit *u);

-  

- diff --git a/src/core/scope.c b/src/core/scope.c

- index 42c51b0865..ffee783a4c 100644

- --- a/src/core/scope.c

- +++ b/src/core/scope.c

- @@ -487,6 +487,11 @@ static void scope_notify_cgroup_empty_event(Unit *u) {

-  

-          if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))

-                  scope_enter_dead(s, SCOPE_SUCCESS);

- +

- +        /* If the cgroup empty notification comes when the unit is not active, we must have failed to clean

- +         * up the cgroup earlier and should do it now. */

- +        if (IN_SET(s->state, SCOPE_DEAD, SCOPE_FAILED))

- +                unit_prune_cgroup(u);

-  }

-  

-  static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {

- diff --git a/src/core/service.c b/src/core/service.c

- index 00e61945ba..db8f596ca6 100644

- --- a/src/core/service.c

- +++ b/src/core/service.c

- @@ -3334,6 +3334,13 @@ static void service_notify_cgroup_empty_event(Unit *u) {

-  

-                  break;

-  

- +        /* If the cgroup empty notification comes when the unit is not active, we must have failed to clean

- +         * up the cgroup earlier and should do it now. */

- +        case SERVICE_DEAD:

- +        case SERVICE_FAILED:

- +                unit_prune_cgroup(u);

- +                break;

- +

-          default:

-                  ;

-          }

- -- 

- 2.24.1

- 

@@ -0,0 +1,337 @@ 

+ From 09e8c6aa71ee4b5ff3ee85fc4855e2c1a246a079 Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Thu, 22 Jul 2021 11:22:33 +0200

+ Subject: [PATCH 2/5] rpm: use a helper script to actually invoke systemctl

+  commands

+ MIME-Version: 1.0

+ Content-Type: text/plain; charset=UTF-8

+ Content-Transfer-Encoding: 8bit

+ 

+ Instead of embedding the commands to invoke directly in the macros,

+ let's use a helper script as indirection. This has a couple of advantages:

+ 

+ - the macro language is awkward, we need to suffix most commands by "|| :"

+   and "\", which is easy to get wrong. In the new scheme, the macro becomes

+   a single simple command.

+ - in the script we can use normal syntax highlighting, shellcheck, etc.

+ - it's also easier to test the invoked commands by invoking the helper

+   manually.

+ - most importantly, the logic is contained in the helper, i.e. we can

+   update systemd rpm and everything uses the new helper. Before, we would

+   have to rebuild all packages to update the macro definition.

+ 

+ This raises the question whether it makes sense to use the lua scriptlets when

+ the real work is done in a bash script. I think it's OK: we still have the

+ efficient lua scripts that do the short scripts, and we use a single shared

+ implementation in bash to do the more complex stuff.

+ 

+ The meson version is raised to 0.47 because that's needed for install_mode.

+ We were planning to raise the required version anyway…

+ 

+ (cherry picked from commit 6d825ab2d42d3219e49a192bf99f9c09134a0df4)

+ ---

+  README                           |  2 +-

+  meson.build                      |  3 +-

+  src/rpm/macros.systemd.in        | 30 ++++++++--------

+  src/rpm/meson.build              | 13 ++++---

+  src/rpm/systemd-update-helper.in | 60 ++++++++++++++++++++++++++++++++

+  src/rpm/triggers.systemd.in      | 43 ++++++++---------------

+  src/rpm/triggers.systemd.sh.in   | 13 ++-----

+  7 files changed, 105 insertions(+), 59 deletions(-)

+  create mode 100755 src/rpm/systemd-update-helper.in

+ 

+ diff --git a/README b/README

+ index 0e5c326deb..a8f23a0d5b 100644

+ --- a/README

+ +++ b/README

+ @@ -193,7 +193,7 @@ REQUIREMENTS:

+          python-jinja2

+          python-lxml (optional, required to build the indices)

+          python >= 3.5

+ -        meson >= 0.46 (>= 0.49 is required to build position-independent executables)

+ +        meson >= 0.47 (>= 0.49 is required to build position-independent executables)

+          ninja

+          gcc, awk, sed, grep, and similar tools

+          clang >= 10.0, llvm >= 10.0 (optional, required to build BPF programs

+ diff --git a/meson.build b/meson.build

+ index 738879eb21..fb986e84f7 100644

+ --- a/meson.build

+ +++ b/meson.build

+ @@ -10,7 +10,7 @@ project('systemd', 'c',

+                  'localstatedir=/var',

+                  'warning_level=2',

+          ],

+ -        meson_version : '>= 0.46',

+ +        meson_version : '>= 0.47',

+         )

+  

+  libsystemd_version = '0.32.0'

+ @@ -253,6 +253,7 @@ conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               join_paths(rootlib

+  conf.set_quoted('SYSTEMD_STDIO_BRIDGE_BINARY_PATH',           join_paths(bindir, 'systemd-stdio-bridge'))

+  conf.set_quoted('SYSTEMD_TEST_DATA',                          join_paths(testsdir, 'testdata'))

+  conf.set_quoted('SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH', join_paths(rootbindir, 'systemd-tty-ask-password-agent'))

+ +conf.set_quoted('SYSTEMD_UPDATE_HELPER_PATH',                 join_paths(rootlibexecdir, 'systemd-update-helper'))

+  conf.set_quoted('SYSTEMD_USERWORK_PATH',                      join_paths(rootlibexecdir, 'systemd-userwork'))

+  conf.set_quoted('SYSTEMD_VERITYSETUP_PATH',                   join_paths(rootlibexecdir, 'systemd-veritysetup'))

+  conf.set_quoted('SYSTEM_CONFIG_UNIT_DIR',                     join_paths(pkgsysconfdir, 'system'))

+ diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in

+ index 3129ab2d61..bbdf036da7 100644

+ --- a/src/rpm/macros.systemd.in

+ +++ b/src/rpm/macros.systemd.in

+ @@ -46,31 +46,33 @@ OrderWithRequires(postun): systemd \

+  

+  %systemd_post() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_post}} \

+ -if [ $1 -eq 1 ] && command -v systemctl >/dev/null; then \

+ +if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+      # Initial installation \

+ -    systemctl --no-reload preset %{?*} || : \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} install-system-units %{?*} || : \

+  fi \

+  %{nil}

+  

+ -%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}}

+ +%systemd_user_post() \

+ +%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_post}} \

+ +if [ $1 -eq 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+ +    # Initial installation \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} install-user-units %{?*} || : \

+ +fi \

+ +%{nil}

+  

+  %systemd_preun() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_preun}} \

+ -if [ $1 -eq 0 ] && command -v systemctl >/dev/null; then \

+ +if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+      # Package removal, not upgrade \

+ -    if [ -d /run/systemd/system ]; then \

+ -          systemctl --no-reload disable --now %{?*} || : \

+ -    else \

+ -          systemctl --no-reload disable %{?*} || : \

+ -    fi \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} remove-system-units %{?*} || : \

+  fi \

+  %{nil}

+  

+  %systemd_user_preun() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_preun}} \

+ -if [ $1 -eq 0 ] && command -v systemctl >/dev/null; then \

+ +if [ $1 -eq 0 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+      # Package removal, not upgrade \

+ -    systemctl --global disable %{?*} || : \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} remove-user-units %{?*} || : \

+  fi \

+  %{nil}

+  

+ @@ -84,11 +86,9 @@ fi \

+  

+  %systemd_postun_with_restart() \

+  %{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \

+ -if [ $1 -ge 1 ] && command -v systemctl >/dev/null; then \

+ +if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+      # Package upgrade, not uninstall \

+ -    for unit in %{?*}; do \

+ -        systemctl set-property $unit Markers=+needs-restart || : \

+ -    done \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-system-units %{?*} || : \

+  fi \

+  %{nil}

+  

+ diff --git a/src/rpm/meson.build b/src/rpm/meson.build

+ index fc72fee73c..2ad3308cc1 100644

+ --- a/src/rpm/meson.build

+ +++ b/src/rpm/meson.build

+ @@ -1,9 +1,13 @@

+  # SPDX-License-Identifier: LGPL-2.1-or-later

+  

+  in_files = [

+ -        ['macros.systemd',      rpmmacrosdir != 'no'],

+ -        ['triggers.systemd',    false],

+ -        ['triggers.systemd.sh', false]]

+ +        ['macros.systemd',        rpmmacrosdir != 'no', rpmmacrosdir],

+ +

+ +        # we conditionalize on rpmmacrosdir, but install into rootlibexecdir

+ +        ['systemd-update-helper', rpmmacrosdir != 'no', rootlibexecdir, 'rwxr-xr-x'],

+ +

+ +        ['triggers.systemd',      false],

+ +        ['triggers.systemd.sh',   false]]

+  

+  # The last two don't get installed anywhere, one of them needs to included in

+  # the rpm spec file definition instead.

+ @@ -17,6 +21,7 @@ foreach tuple : in_files

+                  command : [meson_render_jinja2, config_h, '@INPUT@'],

+                  capture : true,

+                  install : tuple[1],

+ -                install_dir : rpmmacrosdir,

+ +                install_dir : tuple.length() > 2 ? tuple[2] : '',

+ +                install_mode : tuple.length() > 3 ? tuple[3] : false,

+                  build_by_default : true)

+  endforeach

+ diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in

+ new file mode 100755

+ index 0000000000..9fa49fa131

+ --- /dev/null

+ +++ b/src/rpm/systemd-update-helper.in

+ @@ -0,0 +1,60 @@

+ +#!/bin/bash

+ +set -eu

+ +set -o pipefail

+ +

+ +command="${1:?}"

+ +shift

+ +

+ +command -v systemctl >/dev/null || exit 0

+ +

+ +case "$command" in

+ +    install-system-units)

+ +        systemctl --no-reload preset "$@"

+ +        ;;

+ +

+ +    install-user-units)

+ +        systemctl --no-reload preset --global "$@"

+ +        ;;

+ +

+ +    remove-system-units)

+ +        if [ -d /run/systemd/system ]; then

+ +            systemctl --no-reload disable --now "$@"

+ +        else

+ +            systemctl --no-reload disable "$@"

+ +        fi

+ +        ;;

+ +

+ +    remove-user-units)

+ +        systemctl --global disable "$@"

+ +        ;;

+ +

+ +    mark-restart-system-units)

+ +        [ -d /run/systemd/system ] || exit 0

+ +

+ +        for unit in "$@"; do

+ +            systemctl set-property "$unit" Markers=+needs-restart || :

+ +        done

+ +        ;;

+ +

+ +    system-reload-restart|system-reload|system-restart)

+ +        if [ -n "$*" ]; then

+ +            echo "Unexpected arguments for '$command': $*"

+ +            exit 2

+ +        fi

+ +

+ +        [ -d /run/systemd/system ] || exit 0

+ +

+ +        if [[ "$command" =~ reload ]]; then

+ +            systemctl daemon-reload

+ +        fi

+ +

+ +        if [[ "$command" =~ restart ]]; then

+ +            systemctl reload-or-restart --marked

+ +        fi

+ +        ;;

+ +

+ +    *)

+ +        echo "Unknown verb '$command'"

+ +        exit 3

+ +        ;;

+ +esac

+ diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in

+ index 247358008a..d29cc33dfd 100644

+ --- a/src/rpm/triggers.systemd.in

+ +++ b/src/rpm/triggers.systemd.in

+ @@ -13,20 +13,11 @@

+  -- upgraded. We care about the case where a package is initially

+  -- installed, because other cases are covered by the *un scriptlets,

+  -- so sometimes we will reload needlessly.

+ -if posix.access("/run/systemd/system") then

+ -    pid = posix.fork()

+ -    if pid == 0 then

+ -        assert(posix.execp("systemctl", "daemon-reload"))

+ -    elseif pid > 0 then

+ -        posix.wait(pid)

+ -    end

+ -

+ -    pid = posix.fork()

+ -    if pid == 0 then

+ -        assert(posix.execp("systemctl", "reload-or-restart", "--marked"))

+ -    elseif pid > 0 then

+ -        posix.wait(pid)

+ -    end

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload-restart"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+  end

+  

+  %transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+ @@ -35,24 +26,20 @@ end

+  -- On upgrade, we need to run daemon-reload after any new unit files

+  -- have been installed, but before %postun scripts in packages get

+  -- executed.

+ -if posix.access("/run/systemd/system") then

+ -    pid = posix.fork()

+ -    if pid == 0 then

+ -        assert(posix.execp("systemctl", "daemon-reload"))

+ -    elseif pid > 0 then

+ -        posix.wait(pid)

+ -    end

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+  end

+  

+  %transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  -- We restart remaining services that should be restarted here.

+ -if posix.access("/run/systemd/system") then

+ -    pid = posix.fork()

+ -    if pid == 0 then

+ -        assert(posix.execp("systemctl", "reload-or-restart", "--marked"))

+ -    elseif pid > 0 then

+ -        posix.wait(pid)

+ -    end

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+  end

+  

+  %transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}}

+ diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in

+ index 1631be18c9..83cd7617f8 100644

+ --- a/src/rpm/triggers.systemd.sh.in

+ +++ b/src/rpm/triggers.systemd.sh.in

+ @@ -14,10 +14,7 @@

+  # upgraded. We care about the case where a package is initially

+  # installed, because other cases are covered by the *un scriptlets,

+  # so sometimes we will reload needlessly.

+ -if test -d "/run/systemd/system"; then

+ -  systemctl daemon-reload || :

+ -  systemctl reload-or-restart --marked || :

+ -fi

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :

+  

+  %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  # On removal, we need to run daemon-reload after any units have been

+ @@ -25,15 +22,11 @@ fi

+  # On upgrade, we need to run daemon-reload after any new unit files

+  # have been installed, but before %postun scripts in packages get

+  # executed.

+ -if test -d "/run/systemd/system"; then

+ -  systemctl daemon-reload || :

+ -fi

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :

+  

+  %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  # We restart remaining services that should be restarted here.

+ -if test -d "/run/systemd/system"; then

+ -  systemctl reload-or-restart --marked || :

+ -fi

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :

+  

+  %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}

+  # This script will process files installed in {{SYSUSERS_DIR}} to create

+ -- 

+ 2.31.1

+ 

@@ -1,53 +0,0 @@ 

- From a2deeaeaa90d493ef8a2b20656745cd0531a1b30 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Fri, 31 Jul 2020 10:36:57 +0200

- Subject: [PATCH 2/2] test-path: do not fail the test if we fail to start some

-  service

- 

- The test was failing because it couldn't start the service:

- 

- path-modified.service: state = failed; result = exit-code

- path-modified.path: state = waiting; result = success

- path-modified.service: state = failed; result = exit-code

- path-modified.path: state = waiting; result = success

- path-modified.service: state = failed; result = exit-code

- path-modified.path: state = waiting; result = success

- path-modified.service: state = failed; result = exit-code

- path-modified.path: state = waiting; result = success

- path-modified.service: state = failed; result = exit-code

- path-modified.path: state = waiting; result = success

- path-modified.service: state = failed; result = exit-code

- Failed to connect to system bus: No such file or directory

- -.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied

- path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied

- path-modified.service: Failed to attach to cgroup /system.slice/kojid.service/path-modified.service: No such file or directory

- path-modified.service: Failed at step CGROUP spawning /bin/true: No such file or directory

- path-modified.service: Main process exited, code=exited, status=219/CGROUP

- path-modified.service: Failed with result 'exit-code'.

- Test timeout when testing path-modified.path

- 

- Let's just ignore the failure here. Services can occasionally fail to start,

- there's not much we can do in that case.

- ---

-  src/test/test-path.c | 8 ++++++++

-  1 file changed, 8 insertions(+)

- 

- diff --git a/src/test/test-path.c b/src/test/test-path.c

- index 63b709c8da..6c0db53f10 100644

- --- a/src/test/test-path.c

- +++ b/src/test/test-path.c

- @@ -98,6 +98,14 @@ static void check_states(Manager *m, Path *path, Service *service, PathState pat

-                                  service_state_to_string(service->state),

-                                  service_result_to_string(service->result));

-  

- +                if (service->state == SERVICE_FAILED) {

- +                        log_warning("Failed to start service %s, ignoring: %s/%s",

- +                                    UNIT(service)->id,

- +                                    service_state_to_string(service->state),

- +                                    service_result_to_string(service->result));

- +                        break;

- +                }

- +

-                  if (now(CLOCK_MONOTONIC) >= end) {

-                          log_error("Test timeout when testing %s", UNIT(path)->id);

-                          exit(EXIT_FAILURE);

@@ -0,0 +1,35 @@ 

+ From 0a2e691b6b1fdceb4b7504870c4b792a66b5080f Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Thu, 22 Jul 2021 11:28:36 +0200

+ Subject: [PATCH 3/5] rpm: call +needs-restart in parallel

+ MIME-Version: 1.0

+ Content-Type: text/plain; charset=UTF-8

+ Content-Transfer-Encoding: 8bit

+ 

+ Some rpms install a bunch of units… It seems nicer to invoke them all in

+ parallel. In particular, timeouts in systemctl also run in parallel, so if

+ there's some communication mishap, we will wait less.

+ 

+ (cherry picked from commit 3598aff4d963b2e51ac74d206161da47bfde785c)

+ ---

+  src/rpm/systemd-update-helper.in | 3 ++-

+  1 file changed, 2 insertions(+), 1 deletion(-)

+ 

+ diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in

+ index 9fa49fa131..f3c75b75fa 100755

+ --- a/src/rpm/systemd-update-helper.in

+ +++ b/src/rpm/systemd-update-helper.in

+ @@ -32,8 +32,9 @@ case "$command" in

+          [ -d /run/systemd/system ] || exit 0

+  

+          for unit in "$@"; do

+ -            systemctl set-property "$unit" Markers=+needs-restart || :

+ +            systemctl set-property "$unit" Markers=+needs-restart &

+          done

+ +        wait

+          ;;

+  

+      system-reload-restart|system-reload|system-restart)

+ -- 

+ 2.31.1

+ 

@@ -1,234 +0,0 @@ 

- From de8f6fb530db706d14e9ece52b2acfd77c823133 Mon Sep 17 00:00:00 2001

- From: Kristijan Gjoshev <crypter@mail.com>

- Date: Sat, 1 Feb 2020 18:27:08 +0100

- Subject: [PATCH 3/3] timer: add new feature FixedRandomDelay=

- 

- FixedRandomDelay=yes will use

- `siphash24(sd_id128_get_machine() || MANAGER_IS_SYSTEM(m) || getuid() || u->id)`,

- where || is concatenation, instead of a random number to choose a value between

- 0 and RandomizedDelaySec= as the timer delay.

- This essentially sets up a fixed, but seemingly random, offset for each timer

- iteration rather than having a random offset recalculated each time it fires.

- 

- Closes #10355

- 

- Co-author: Anita Zhang <the.anitazha@gmail.com>

- ---

-  docs/TRANSIENT-SETTINGS.md                    |  1 +

-  man/org.freedesktop.systemd1.xml              |  6 ++++

-  man/systemd.timer.xml                         | 12 +++++++

-  src/core/dbus-timer.c                         |  4 +++

-  src/core/timer.c                              | 34 ++++++++++++++++++-

-  src/core/timer.h                              |  1 +

-  src/shared/bus-unit-util.c                    |  3 +-

-  test/fuzz/fuzz-unit-file/directives.service   |  1 +

-  .../systemd-tmpfiles-clean.timer              |  1 +

-  9 files changed, 61 insertions(+), 2 deletions(-)

- 

- diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md

- index 19944d08b8..f4639b2e87 100644

- --- a/docs/TRANSIENT-SETTINGS.md

- +++ b/docs/TRANSIENT-SETTINGS.md

- @@ -368,6 +368,7 @@ Most timer unit settings are available to transient units.

-  ✓ RemainAfterElapse=

-  ✓ AccuracySec=

-  ✓ RandomizedDelaySec=

- +✓ FixedRandomDelay=

-    Unit=

-  ```

-  

- diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml

- index 6b16ae16da..ab4cbaa2fb 100644

- --- a/man/org.freedesktop.systemd1.xml

- +++ b/man/org.freedesktop.systemd1.xml

- @@ -6866,6 +6866,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {

-        @org.freedesktop.DBus.Property.EmitsChangedSignal("const")

-        readonly t RandomizedDelayUSec = ...;

-        @org.freedesktop.DBus.Property.EmitsChangedSignal("const")

- +      readonly b FixedRandomDelay = ...;

- +      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")

-        readonly b Persistent = ...;

-        @org.freedesktop.DBus.Property.EmitsChangedSignal("const")

-        readonly b WakeSystem = ...;

- @@ -6891,6 +6893,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {

-  

-      <!--property RandomizedDelayUSec is not documented!-->

-  

- +    <!--property FixedRandomDelay is not documented!-->

- +

-      <!--property Persistent is not documented!-->

-  

-      <!--property WakeSystem is not documented!-->

- @@ -6931,6 +6935,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {

-  

-      <variablelist class="dbus-property" generated="True" extra-ref="RandomizedDelayUSec"/>

-  

- +    <variablelist class="dbus-property" generated="True" extra-ref="FixedRandomDelay"/>

- +

-      <variablelist class="dbus-property" generated="True" extra-ref="Persistent"/>

-  

-      <variablelist class="dbus-property" generated="True" extra-ref="WakeSystem"/>

- diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml

- index 5822402712..6f731e2311 100644

- --- a/man/systemd.timer.xml

- +++ b/man/systemd.timer.xml

- @@ -268,6 +268,18 @@

-          <varname>AccuracySec=1us</varname>.</para></listitem>

-        </varlistentry>

-  

- +      <varlistentry>

- +        <term><varname>FixedRandomDelay=</varname></term>

- +

- +        <listitem><para>Takes a boolean argument. If true, some amount of time between 0 and

- +        <varname>RandomizedDelaySec=</varname> is chosen and added as the delay for each timer iteration. As this

- +        delay will not be recalculated on each run, this effectively creates a fixed offset for each iteration.

- +        The distribution between 0 and <varname>RandomizedDelaySec=</varname> is deterministic and based on

- +        a combination of the machine ID, whether the timer is run by the user/system manager, the service manager's

- +        user ID, and the timer's unit name. Has no effect if

- +        <varname>RandomizedDelaySec=</varname> is set to 0. Defaults to <option>false</option>.</para></listitem>

- +      </varlistentry>

- +

-        <varlistentry>

-          <term><varname>OnClockChange=</varname></term>

-          <term><varname>OnTimezoneChange=</varname></term>

- diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c

- index da35fa8678..ee54ba8772 100644

- --- a/src/core/dbus-timer.c

- +++ b/src/core/dbus-timer.c

- @@ -131,6 +131,7 @@ const sd_bus_vtable bus_timer_vtable[] = {

-          SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),

-          SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),

-          SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),

- +        SD_BUS_PROPERTY("FixedRandomDelay", "b", bus_property_get_bool, offsetof(Timer, fixed_random_delay), SD_BUS_VTABLE_PROPERTY_CONST),

-          SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),

-          SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),

-          SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),

- @@ -232,6 +233,9 @@ static int bus_timer_set_transient_property(

-          if (streq(name, "RandomizedDelayUSec"))

-                  return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error);

-  

- +        if (streq(name, "FixedRandomDelay"))

- +                return bus_set_transient_bool(u, name, &t->fixed_random_delay, message, flags, error);

- +

-          if (streq(name, "WakeSystem"))

-                  return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error);

-  

- diff --git a/src/core/timer.c b/src/core/timer.c

- index 03a9c14f76..b2c5e26f63 100644

- --- a/src/core/timer.c

- +++ b/src/core/timer.c

- @@ -169,6 +169,36 @@ static int timer_setup_persistent(Timer *t) {

-          return 0;

-  }

-  

- +static uint64_t timer_get_fixed_delay_hash(Timer *t) {

- +        static const uint8_t hash_key[] = {

- +                0x51, 0x0a, 0xdb, 0x76, 0x29, 0x51, 0x42, 0xc2,

- +                0x80, 0x35, 0xea, 0xe6, 0x8e, 0x3a, 0x37, 0xbd

- +        };

- +

- +        struct siphash state;

- +        sd_id128_t machine_id;

- +        uid_t uid;

- +        int r;

- +

- +        assert(t);

- +

- +        uid = getuid();

- +        r = sd_id128_get_machine(&machine_id);

- +        if (r < 0) {

- +                log_unit_debug_errno(UNIT(t), r,

- +                                     "Failed to get machine ID for the fixed delay calculation, proceeding with 0: %m");

- +                machine_id = SD_ID128_NULL;

- +        }

- +

- +        siphash24_init(&state, hash_key);

- +        siphash24_compress(&machine_id, sizeof(sd_id128_t), &state);

- +        siphash24_compress_boolean(MANAGER_IS_SYSTEM(UNIT(t)->manager), &state);

- +        siphash24_compress(&uid, sizeof(uid_t), &state);

- +        siphash24_compress_string(UNIT(t)->id, &state);

- +

- +        return siphash24_finalize(&state);

- +}

- +

-  static int timer_load(Unit *u) {

-          Timer *t = TIMER(u);

-          int r;

- @@ -215,6 +245,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {

-                  "%sWakeSystem: %s\n"

-                  "%sAccuracy: %s\n"

-                  "%sRemainAfterElapse: %s\n"

- +                "%sFixedRandomDelay: %s\n"

-                  "%sOnClockChange: %s\n"

-                  "%sOnTimeZoneChange: %s\n",

-                  prefix, timer_state_to_string(t->state),

- @@ -224,6 +255,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {

-                  prefix, yes_no(t->wake_system),

-                  prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),

-                  prefix, yes_no(t->remain_after_elapse),

- +                prefix, yes_no(t->fixed_random_delay),

-                  prefix, yes_no(t->on_clock_change),

-                  prefix, yes_no(t->on_timezone_change));

-  

- @@ -332,7 +364,7 @@ static void add_random(Timer *t, usec_t *v) {

-          if (*v == USEC_INFINITY)

-                  return;

-  

- -        add = random_u64() % t->random_usec;

- +        add = (t->fixed_random_delay ? timer_get_fixed_delay_hash(t) : random_u64()) % t->random_usec;

-  

-          if (*v + add < *v) /* overflow */

-                  *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */

- diff --git a/src/core/timer.h b/src/core/timer.h

- index ab66a201ad..ce4046a210 100644

- --- a/src/core/timer.h

- +++ b/src/core/timer.h

- @@ -59,6 +59,7 @@ struct Timer {

-          bool remain_after_elapse;

-          bool on_clock_change;

-          bool on_timezone_change;

- +        bool fixed_random_delay;

-  

-          char *stamp_path;

-  };

- diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c

- index f2652ed9a5..68de4a2ed1 100644

- --- a/src/shared/bus-unit-util.c

- +++ b/src/shared/bus-unit-util.c

- @@ -1779,7 +1779,8 @@ static int bus_append_timer_property(sd_bus_message *m, const char *field, const

-                                "RemainAfterElapse",

-                                "Persistent",

-                                "OnTimezoneChange",

- -                              "OnClockChange"))

- +                              "OnClockChange",

- +                              "FixedRandomDelay"))

-                  return bus_append_parse_boolean(m, field, eq);

-  

-          if (STR_IN_SET(field, "AccuracySec",

- diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service

- index dbff9ab2cc..95304ea0c6 100644

- --- a/test/fuzz/fuzz-unit-file/directives.service

- +++ b/test/fuzz/fuzz-unit-file/directives.service

- @@ -175,6 +175,7 @@ PipeSize=

-  Priority=

-  PropagatesReloadTo=

-  RandomizedDelaySec=

- +FixedRandomDelay=

-  RebootArgument=

-  ReceiveBuffer=

-  RefuseManualStart=

- diff --git a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer

- index 7db361cd69..64b8808adc 100644

- --- a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer

- +++ b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer

- @@ -32,6 +32,7 @@ OnCalendar=Fri 2012-11-23 11:12:13

-  Persistent=true

-  AccuracySec=24h

-  RandomizedDelaySec=234234234

- +FixedRandomDelay=true

-  

-  Persistent=no

-  Unit=foo.service

- -- 

- 2.24.1

- 

@@ -0,0 +1,259 @@ 

+ From a63d5d320f81c1cbae07897a401ed5cc5374e0bf Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Wed, 7 Jul 2021 14:37:57 +0200

+ Subject: [PATCH 4/5] rpm: restart user services at the end of the transaction

+ 

+ This closes an important gap: so far we would reexecute the system manager and

+ restart system services that were configured to do so, but we wouldn't do the

+ same for user managers or user services.

+ 

+ The scheme used for user managers is very similar to the system one, except

+ that there can be multiple user managers running, so we query the system

+ manager to get a list of them, and then tell each one to do the equivalent

+ operations: daemon-reload, disable --now, set-property Markers=+needs-restart,

+ reload-or-restart --marked.

+ 

+ The total time that can be spend on this is bounded: we execute the commands in

+ parallel over user managers and units, and additionally set SYSTEMD_BUS_TIMEOUT

+ to a lower value (15 s by default). User managers should not have too many

+ units running, and they should be able to do all those operations very

+ quickly (<< 1s). The final restart operation may take longer, but it's done

+ asynchronously, so we only wait for the queuing to happen.

+ 

+ The advantage of doing this synchronously is that we can wait for each step to

+ happen, and for example daemon-reloads can finish before we execute the service

+ restarts, etc. We can also order various steps wrt. to the phases in the rpm

+ transaction.

+ 

+ When this was initially proposed, we discussed a more relaxed scheme with bus

+ property notifications. Such an approach would be more complex because a bunch

+ of infrastructure would have to be added to system manager to propagate

+ appropriate notifications to the user managers, and then the user managers

+ would have to wait for them. Instead, now there is no new code in the managers,

+ all new functionality is contained in src/rpm/. The ability to call 'systemctl

+ --user user@' makes this approach very easy. Also, it would be very hard to

+ order the user manager steps and the rpm transaction steps.

+ 

+ Note: 'systemctl --user disable' is only called for a user managers that are

+ running. I don't see a nice way around this, and it shouldn't matter too much:

+ we'll just leave a dangling symlink in the case where the user enabled the

+ service manually.

+ 

+ A follow-up for https://bugzilla.redhat.com/show_bug.cgi?id=1792468 and

+ fa97d2fcf64e0558054bee673f734f523373b146.

+ 

+ (cherry picked from commit 36d55958ccc75fa3c91bdd7354d74c910f2f6cc7)

+ ---

+  meson.build                      |  1 +

+  meson_options.txt                |  2 ++

+  src/rpm/macros.systemd.in        |  6 +++-

+  src/rpm/systemd-update-helper.in | 47 ++++++++++++++++++++++++++++++++

+  src/rpm/triggers.systemd.in      | 28 ++++++++++++++++++-

+  src/rpm/triggers.systemd.sh.in   | 13 ++++++++-

+  6 files changed, 94 insertions(+), 3 deletions(-)

+ 

+ diff --git a/meson.build b/meson.build

+ index fb986e84f7..d898d9ccd0 100644

+ --- a/meson.build

+ +++ b/meson.build

+ @@ -270,6 +270,7 @@ conf.set_quoted('TMPFILES_DIR',                               tmpfilesdir)

+  conf.set_quoted('UDEVLIBEXECDIR',                             udevlibexecdir)

+  conf.set_quoted('UDEV_HWDB_DIR',                              udevhwdbdir)

+  conf.set_quoted('UDEV_RULES_DIR',                             udevrulesdir)

+ +conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT',                 get_option('update-helper-user-timeout'))

+  conf.set_quoted('USER_CONFIG_UNIT_DIR',                       join_paths(pkgsysconfdir, 'user'))

+  conf.set_quoted('USER_DATA_UNIT_DIR',                         userunitdir)

+  conf.set_quoted('USER_ENV_GENERATOR_DIR',                     userenvgeneratordir)

+ diff --git a/meson_options.txt b/meson_options.txt

+ index 163c8df87d..9383c7da6a 100644

+ --- a/meson_options.txt

+ +++ b/meson_options.txt

+ @@ -182,6 +182,8 @@ option('xinitrcdir', type : 'string', value : '',

+         description : 'directory for xinitrc files')

+  option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',

+         description : 'directory for rpm macros ["no" disables]')

+ +option('update-helper-user-timeout', type : 'string', value : '15s',

+ +       description : 'how long to wait for user manager operations')

+  option('pamlibdir', type : 'string',

+         description : 'directory for PAM modules')

+  option('pamconfdir', type : 'string',

+ diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in

+ index bbdf036da7..caa2e45595 100644

+ --- a/src/rpm/macros.systemd.in

+ +++ b/src/rpm/macros.systemd.in

+ @@ -93,7 +93,11 @@ fi \

+  %{nil}

+  

+  %systemd_user_postun_with_restart() \

+ -%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \

+ +%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_restart}} \

+ +if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \

+ +    # Package upgrade, not uninstall \

+ +    {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-user-units %{?*} || : \

+ +fi \

+  %{nil}

+  

+  %udev_hwdb_update() %{nil}

+ diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in

+ index f3c75b75fa..f3466ab3c0 100755

+ --- a/src/rpm/systemd-update-helper.in

+ +++ b/src/rpm/systemd-update-helper.in

+ @@ -26,6 +26,15 @@ case "$command" in

+  

+      remove-user-units)

+          systemctl --global disable "$@"

+ +

+ +        [ -d /run/systemd/system ] || exit 0

+ +

+ +        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')

+ +        for user in $users; do

+ +            SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ +                    systemctl --user -M "$user@" disable --now "$@" &

+ +        done

+ +        wait

+          ;;

+  

+      mark-restart-system-units)

+ @@ -37,6 +46,17 @@ case "$command" in

+          wait

+          ;;

+  

+ +    mark-restart-user-units)

+ +        [ -d /run/systemd/system ] || exit 0

+ +

+ +        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')

+ +        for user in $users; do

+ +            SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ +                    systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &

+ +        done

+ +        wait

+ +        ;;

+ +

+      system-reload-restart|system-reload|system-restart)

+          if [ -n "$*" ]; then

+              echo "Unexpected arguments for '$command': $*"

+ @@ -54,6 +74,33 @@ case "$command" in

+          fi

+          ;;

+  

+ +    user-reload-restart|user-reload|user-restart)

+ +        if [ -n "$*" ]; then

+ +            echo "Unexpected arguments for '$command': $*"

+ +            exit 2

+ +        fi

+ +

+ +        [ -d /run/systemd/system ] || exit 0

+ +

+ +        users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')

+ +

+ +        if [[ "$command" =~ reload ]]; then

+ +            for user in $users; do

+ +                SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ +                        systemctl --user -M "$user@" daemon-reload &

+ +            done

+ +            wait

+ +        fi

+ +

+ +        if [[ "$command" =~ restart ]]; then

+ +            for user in $users; do

+ +                SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ +                        systemctl --user -M "$user@" reload-or-restart --marked &

+ +            done

+ +            wait

+ +        fi

+ +        ;;

+ +

+      *)

+          echo "Unknown verb '$command'"

+          exit 3

+ diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in

+ index d29cc33dfd..8aeb2049c1 100644

+ --- a/src/rpm/triggers.systemd.in

+ +++ b/src/rpm/triggers.systemd.in

+ @@ -20,6 +20,14 @@ elseif pid > 0 then

+      posix.wait(pid)

+  end

+  

+ +%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+ +end

+ +

+  %transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  -- On removal, we need to run daemon-reload after any units have been

+  -- removed.

+ @@ -33,8 +41,17 @@ elseif pid > 0 then

+      posix.wait(pid)

+  end

+  

+ +%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+ +-- Execute daemon-reload in user managers.

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+ +end

+ +

+  %transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+ --- We restart remaining services that should be restarted here.

+ +-- We restart remaining system services that should be restarted here.

+  pid = posix.fork()

+  if pid == 0 then

+      assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))

+ @@ -42,6 +59,15 @@ elseif pid > 0 then

+      posix.wait(pid)

+  end

+  

+ +%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user

+ +-- We restart remaining user services that should be restarted here.

+ +pid = posix.fork()

+ +if pid == 0 then

+ +    assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))

+ +elseif pid > 0 then

+ +    posix.wait(pid)

+ +end

+ +

+  %transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}}

+  -- This script will process files installed in {{SYSUSERS_DIR}} to create

+  -- specified users automatically. The priority is set such that it

+ diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in

+ index 83cd7617f8..694cd94e8d 100644

+ --- a/src/rpm/triggers.systemd.sh.in

+ +++ b/src/rpm/triggers.systemd.sh.in

+ @@ -16,6 +16,9 @@

+  # so sometimes we will reload needlessly.

+  {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :

+  

+ +%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :

+ +

+  %transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+  # On removal, we need to run daemon-reload after any units have been

+  # removed.

+ @@ -24,10 +27,18 @@

+  # executed.

+  {{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :

+  

+ +%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user

+ +# Execute daemon-reload in user managers.

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :

+ +

+  %transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system

+ -# We restart remaining services that should be restarted here.

+ +# We restart remaining system services that should be restarted here.

+  {{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :

+  

+ +%transfiletriggerpostun -P  9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user

+ +# We restart remaining user services that should be restarted here.

+ +{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :

+ +

+  %transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}

+  # This script will process files installed in {{SYSUSERS_DIR}} to create

+  # specified users automatically. The priority is set such that it

+ -- 

+ 2.31.1

+ 

@@ -0,0 +1,47 @@ 

+ From 37cd6c0fad847e5fffd9d107358a36e767c7ca42 Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Fri, 23 Jul 2021 15:35:23 +0200

+ Subject: [PATCH 5/5] update-helper: also add "user-reexec" verb

+ 

+ This is not called from the systemd.triggers or systemd.macros files. Instead,

+ it would be called from the scriptlets in systemd rpm package itself, at the

+ place where we call systemctl daemon-reexec.

+ 

+ See https://github.com/systemd/systemd/pull/20289#issuecomment-885622200 .

+ 

+ (cherry picked from commit 1262e824a4d638e347ae0d39c973f1f750962533)

+ ---

+  src/rpm/systemd-update-helper.in | 10 +++++++++-

+  1 file changed, 9 insertions(+), 1 deletion(-)

+ 

+ diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in

+ index f3466ab3c0..0c6675a9db 100755

+ --- a/src/rpm/systemd-update-helper.in

+ +++ b/src/rpm/systemd-update-helper.in

+ @@ -74,7 +74,7 @@ case "$command" in

+          fi

+          ;;

+  

+ -    user-reload-restart|user-reload|user-restart)

+ +    user-reload-restart|user-reload|user-restart|user-reexec)

+          if [ -n "$*" ]; then

+              echo "Unexpected arguments for '$command': $*"

+              exit 2

+ @@ -84,6 +84,14 @@ case "$command" in

+  

+          users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')

+  

+ +        if [[ "$command" =~ reexec ]]; then

+ +            for user in $users; do

+ +                SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ +                        systemctl --user -M "$user@" daemon-reexec &

+ +            done

+ +            wait

+ +        fi

+ +

+          if [[ "$command" =~ reload ]]; then

+              for user in $users; do

+                  SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \

+ -- 

+ 2.31.1

+ 

@@ -0,0 +1,2 @@ 

+ [OOM]

+ DefaultMemoryPressureDurationSec=20s

@@ -0,0 +1,2 @@ 

+ [Slice]

+ ManagedOOMSwap=kill

@@ -0,0 +1,3 @@ 

+ [Service]

+ ManagedOOMMemoryPressure=kill

+ ManagedOOMMemoryPressureLimit=50%

@@ -1,553 +0,0 @@ 

- From 625a164069aff9efb61dcc5916c572f53c2a7ab0 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Thu, 20 Aug 2020 13:43:00 +0200

- Subject: [PATCH 1/3] analyze: rework condition testing

- 

- Let's drop the private table and just use the generic concepts we have

- in place already that make the same information available.

- 

- Fixes: #16781

- ---

-  src/analyze/analyze-condition.c | 105 +++++++++-----------------------

-  1 file changed, 28 insertions(+), 77 deletions(-)

- 

- diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c

- index 52ad382637f..13f75e813a2 100644

- --- a/src/analyze/analyze-condition.c

- +++ b/src/analyze/analyze-condition.c

- @@ -8,83 +8,27 @@

-  #include "load-fragment.h"

-  #include "service.h"

-  

- -typedef struct condition_definition {

- -        const char *name;

- -        ConfigParserCallback parser;

- -        ConditionType type;

- -} condition_definition;

- -

- -static const condition_definition condition_definitions[] = {

- -        { "ConditionPathExists",             config_parse_unit_condition_path,   CONDITION_PATH_EXISTS              },

- -        { "ConditionPathExistsGlob",         config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB         },

- -        { "ConditionPathIsDirectory",        config_parse_unit_condition_path,   CONDITION_PATH_IS_DIRECTORY        },

- -        { "ConditionPathIsSymbolicLink",     config_parse_unit_condition_path,   CONDITION_PATH_IS_SYMBOLIC_LINK    },

- -        { "ConditionPathIsMountPoint",       config_parse_unit_condition_path,   CONDITION_PATH_IS_MOUNT_POINT      },

- -        { "ConditionPathIsReadWrite",        config_parse_unit_condition_path,   CONDITION_PATH_IS_READ_WRITE       },

- -        { "ConditionPathIsEncrypted",        config_parse_unit_condition_path,   CONDITION_PATH_IS_ENCRYPTED        },

- -        { "ConditionDirectoryNotEmpty",      config_parse_unit_condition_path,   CONDITION_DIRECTORY_NOT_EMPTY      },

- -        { "ConditionFileNotEmpty",           config_parse_unit_condition_path,   CONDITION_FILE_NOT_EMPTY           },

- -        { "ConditionFileIsExecutable",       config_parse_unit_condition_path,   CONDITION_FILE_IS_EXECUTABLE       },

- -        { "ConditionNeedsUpdate",            config_parse_unit_condition_path,   CONDITION_NEEDS_UPDATE             },

- -        { "ConditionFirstBoot",              config_parse_unit_condition_string, CONDITION_FIRST_BOOT               },

- -        { "ConditionKernelCommandLine",      config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE      },

- -        { "ConditionKernelVersion",          config_parse_unit_condition_string, CONDITION_KERNEL_VERSION           },

- -        { "ConditionArchitecture",           config_parse_unit_condition_string, CONDITION_ARCHITECTURE             },

- -        { "ConditionVirtualization",         config_parse_unit_condition_string, CONDITION_VIRTUALIZATION           },

- -        { "ConditionSecurity",               config_parse_unit_condition_string, CONDITION_SECURITY                 },

- -        { "ConditionCapability",             config_parse_unit_condition_string, CONDITION_CAPABILITY               },

- -        { "ConditionHost",                   config_parse_unit_condition_string, CONDITION_HOST                     },

- -        { "ConditionACPower",                config_parse_unit_condition_string, CONDITION_AC_POWER                 },

- -        { "ConditionUser",                   config_parse_unit_condition_string, CONDITION_USER                     },

- -        { "ConditionGroup",                  config_parse_unit_condition_string, CONDITION_GROUP                    },

- -        { "ConditionControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER },

- -

- -        { "AssertPathExists",                config_parse_unit_condition_path,   CONDITION_PATH_EXISTS              },

- -        { "AssertPathExistsGlob",            config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB         },

- -        { "AssertPathIsDirectory",           config_parse_unit_condition_path,   CONDITION_PATH_IS_DIRECTORY        },

- -        { "AssertPathIsSymbolicLink",        config_parse_unit_condition_path,   CONDITION_PATH_IS_SYMBOLIC_LINK    },

- -        { "AssertPathIsMountPoint",          config_parse_unit_condition_path,   CONDITION_PATH_IS_MOUNT_POINT      },

- -        { "AssertPathIsReadWrite",           config_parse_unit_condition_path,   CONDITION_PATH_IS_READ_WRITE       },

- -        { "AssertPathIsEncrypted",           config_parse_unit_condition_path,   CONDITION_PATH_IS_ENCRYPTED        },

- -        { "AssertDirectoryNotEmpty",         config_parse_unit_condition_path,   CONDITION_DIRECTORY_NOT_EMPTY      },

- -        { "AssertFileNotEmpty",              config_parse_unit_condition_path,   CONDITION_FILE_NOT_EMPTY           },

- -        { "AssertFileIsExecutable",          config_parse_unit_condition_path,   CONDITION_FILE_IS_EXECUTABLE       },

- -        { "AssertNeedsUpdate",               config_parse_unit_condition_path,   CONDITION_NEEDS_UPDATE             },

- -        { "AssertFirstBoot",                 config_parse_unit_condition_string, CONDITION_FIRST_BOOT               },

- -        { "AssertKernelCommandLine",         config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE      },

- -        { "AssertKernelVersion",             config_parse_unit_condition_string, CONDITION_KERNEL_VERSION           },

- -        { "AssertArchitecture",              config_parse_unit_condition_string, CONDITION_ARCHITECTURE             },

- -        { "AssertVirtualization",            config_parse_unit_condition_string, CONDITION_VIRTUALIZATION           },

- -        { "AssertSecurity",                  config_parse_unit_condition_string, CONDITION_SECURITY                 },

- -        { "AssertCapability",                config_parse_unit_condition_string, CONDITION_CAPABILITY               },

- -        { "AssertHost",                      config_parse_unit_condition_string, CONDITION_HOST                     },

- -        { "AssertACPower",                   config_parse_unit_condition_string, CONDITION_AC_POWER                 },

- -        { "AssertUser",                      config_parse_unit_condition_string, CONDITION_USER                     },

- -        { "AssertGroup",                     config_parse_unit_condition_string, CONDITION_GROUP                    },

- -        { "AssertControlGroupController",    config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER },

- -

- -        /* deprecated, but we should still parse them */

- -        { "ConditionNull",                   config_parse_unit_condition_null,   0                                  },

- -        { "AssertNull",                      config_parse_unit_condition_null,   0                                  },

- -};

- -

-  static int parse_condition(Unit *u, const char *line) {

- -        const char *p;

- -        Condition **target;

- -

- -        if ((p = startswith(line, "Condition")))

- -                target = &u->conditions;

- -        else if ((p = startswith(line, "Assert")))

- -                target = &u->asserts;

- -        else

- -                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line);

- -

- -        for (size_t i = 0; i < ELEMENTSOF(condition_definitions); i++) {

- -                const condition_definition *c = &condition_definitions[i];

- -

- -                p = startswith(line, c->name);

- -                if (!p)

- -                        continue;

- +        assert(u);

- +        assert(line);

- +

- +        for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) {

- +                ConfigParserCallback callback;

- +                Condition **target;

- +                const char *p, *name;

- +

- +                name = condition_type_to_string(t);

- +                p = startswith(line, name);

- +                if (p)

- +                        target = &u->conditions;

- +                else {

- +                        name = assert_type_to_string(t);

- +                        p = startswith(line, name);

- +                        if (!p)

- +                                continue;

- +

- +                        target = &u->asserts;

- +                }

-  

-                  p += strspn(p, WHITESPACE);

-  

- @@ -94,7 +38,14 @@ static int parse_condition(Unit *u, const char *line) {

-  

-                  p += strspn(p, WHITESPACE);

-  

- -                return c->parser(NULL, "(stdin)", 0, NULL, 0, c->name, c->type, p, target, u);

- +                if (t == CONDITION_NULL) /* deprecated, but we should still parse this for now */

- +                        callback = config_parse_unit_condition_null;

- +                else if (condition_takes_path(t))

- +                        callback = config_parse_unit_condition_path;

- +                else

- +                        callback = config_parse_unit_condition_string;

- +

- +                return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u);

-          }

-  

-          return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line);

- 

- From 4f55a5b0bf1e68e4595120d8ac4b518654355fc3 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Thu, 20 Aug 2020 13:44:12 +0200

- Subject: [PATCH 2/3] core: add missing conditions/asserts to unit file parsing

- 

- ---

-  src/core/load-fragment-gperf.gperf.m4 | 24 ++++++++++++++++--------

-  1 file changed, 16 insertions(+), 8 deletions(-)

- 

- diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4

- index b9e7769e4e3..1e6bd6483c2 100644

- --- a/src/core/load-fragment-gperf.gperf.m4

- +++ b/src/core/load-fragment-gperf.gperf.m4

- @@ -272,22 +272,26 @@ Unit.ConditionPathIsDirectory,   config_parse_unit_condition_path,   CONDITION_P

-  Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path,   CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions)

-  Unit.ConditionPathIsMountPoint,  config_parse_unit_condition_path,   CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions)

-  Unit.ConditionPathIsReadWrite,   config_parse_unit_condition_path,   CONDITION_PATH_IS_READ_WRITE,  offsetof(Unit, conditions)

- +Unit.ConditionPathIsEncrypted,   config_parse_unit_condition_path,   CONDITION_PATH_IS_ENCRYPTED,   offsetof(Unit, conditions)

-  Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path,   CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions)

-  Unit.ConditionFileNotEmpty,      config_parse_unit_condition_path,   CONDITION_FILE_NOT_EMPTY,      offsetof(Unit, conditions)

-  Unit.ConditionFileIsExecutable,  config_parse_unit_condition_path,   CONDITION_FILE_IS_EXECUTABLE,  offsetof(Unit, conditions)

-  Unit.ConditionNeedsUpdate,       config_parse_unit_condition_path,   CONDITION_NEEDS_UPDATE,        offsetof(Unit, conditions)

-  Unit.ConditionFirstBoot,         config_parse_unit_condition_string, CONDITION_FIRST_BOOT,          offsetof(Unit, conditions)

- -Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)

- -Unit.ConditionKernelVersion,     config_parse_unit_condition_string, CONDITION_KERNEL_VERSION,      offsetof(Unit, conditions)

-  Unit.ConditionArchitecture,      config_parse_unit_condition_string, CONDITION_ARCHITECTURE,        offsetof(Unit, conditions)

-  Unit.ConditionVirtualization,    config_parse_unit_condition_string, CONDITION_VIRTUALIZATION,      offsetof(Unit, conditions)

- +Unit.ConditionHost,              config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, conditions)

- +Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions)

- +Unit.ConditionKernelVersion,     config_parse_unit_condition_string, CONDITION_KERNEL_VERSION,      offsetof(Unit, conditions)

-  Unit.ConditionSecurity,          config_parse_unit_condition_string, CONDITION_SECURITY,            offsetof(Unit, conditions)

-  Unit.ConditionCapability,        config_parse_unit_condition_string, CONDITION_CAPABILITY,          offsetof(Unit, conditions)

- -Unit.ConditionHost,              config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, conditions)

-  Unit.ConditionACPower,           config_parse_unit_condition_string, CONDITION_AC_POWER,            offsetof(Unit, conditions)

- +Unit.ConditionMemory,            config_parse_unit_condition_string, CONDITION_MEMORY,              offsetof(Unit, conditions)

- +Unit.ConditionCPUs,              config_parse_unit_condition_string, CONDITION_CPUS,                offsetof(Unit, conditions)

- +Unit.ConditionEnvironment,       config_parse_unit_condition_string, CONDITION_ENVIRONMENT,         offsetof(Unit, conditions)

-  Unit.ConditionUser,              config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, conditions)

-  Unit.ConditionGroup,             config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, conditions)

- -Unit.ConditionControlGroupController,  config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER,   offsetof(Unit, conditions)

- +Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions)

-  Unit.ConditionNull,              config_parse_unit_condition_null,   0,                             offsetof(Unit, conditions)

-  Unit.AssertPathExists,           config_parse_unit_condition_path,   CONDITION_PATH_EXISTS,         offsetof(Unit, asserts)

-  Unit.AssertPathExistsGlob,       config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB,    offsetof(Unit, asserts)

- @@ -295,22 +299,26 @@ Unit.AssertPathIsDirectory,      config_parse_unit_condition_path,   CONDITION_P

-  Unit.AssertPathIsSymbolicLink,   config_parse_unit_condition_path,   CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts)

-  Unit.AssertPathIsMountPoint,     config_parse_unit_condition_path,   CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts)

-  Unit.AssertPathIsReadWrite,      config_parse_unit_condition_path,   CONDITION_PATH_IS_READ_WRITE,  offsetof(Unit, asserts)

- +Unit.AssertPathIsEncrypted,      config_parse_unit_condition_path,   CONDITION_PATH_IS_ENCRYPTED,   offsetof(Unit, asserts)

-  Unit.AssertDirectoryNotEmpty,    config_parse_unit_condition_path,   CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts)

-  Unit.AssertFileNotEmpty,         config_parse_unit_condition_path,   CONDITION_FILE_NOT_EMPTY,      offsetof(Unit, asserts)

-  Unit.AssertFileIsExecutable,     config_parse_unit_condition_path,   CONDITION_FILE_IS_EXECUTABLE,  offsetof(Unit, asserts)

-  Unit.AssertNeedsUpdate,          config_parse_unit_condition_path,   CONDITION_NEEDS_UPDATE,        offsetof(Unit, asserts)

-  Unit.AssertFirstBoot,            config_parse_unit_condition_string, CONDITION_FIRST_BOOT,          offsetof(Unit, asserts)

- -Unit.AssertKernelCommandLine,    config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)

- -Unit.AssertKernelVersion,        config_parse_unit_condition_string, CONDITION_KERNEL_VERSION,      offsetof(Unit, asserts)

-  Unit.AssertArchitecture,         config_parse_unit_condition_string, CONDITION_ARCHITECTURE,        offsetof(Unit, asserts)

-  Unit.AssertVirtualization,       config_parse_unit_condition_string, CONDITION_VIRTUALIZATION,      offsetof(Unit, asserts)

- +Unit.AssertHost,                 config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, asserts)

- +Unit.AssertKernelCommandLine,    config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts)

- +Unit.AssertKernelVersion,        config_parse_unit_condition_string, CONDITION_KERNEL_VERSION,      offsetof(Unit, asserts)

-  Unit.AssertSecurity,             config_parse_unit_condition_string, CONDITION_SECURITY,            offsetof(Unit, asserts)

-  Unit.AssertCapability,           config_parse_unit_condition_string, CONDITION_CAPABILITY,          offsetof(Unit, asserts)

- -Unit.AssertHost,                 config_parse_unit_condition_string, CONDITION_HOST,                offsetof(Unit, asserts)

-  Unit.AssertACPower,              config_parse_unit_condition_string, CONDITION_AC_POWER,            offsetof(Unit, asserts)

- +Unit.AssertMemory,               config_parse_unit_condition_string, CONDITION_MEMORY,              offsetof(Unit, asserts)

- +Unit.AssertCPUs,                 config_parse_unit_condition_string, CONDITION_CPUS,                offsetof(Unit, asserts)

- +Unit.AssertEnvironment,          config_parse_unit_condition_string, CONDITION_ENVIRONMENT,         offsetof(Unit, asserts)

-  Unit.AssertUser,                 config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, asserts)

-  Unit.AssertGroup,                config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, asserts)

- -Unit.AssertControlGroupController,     config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER,   offsetof(Unit, asserts)

- +Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts)

-  Unit.AssertNull,                 config_parse_unit_condition_null,   0,                             offsetof(Unit, asserts)

-  Unit.CollectMode,                config_parse_collect_mode,          0,                             offsetof(Unit, collect_mode)

-  m4_dnl

- 

- From 476cfe626dac41bb9879116c701333caa2ccec24 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Thu, 20 Aug 2020 14:01:25 +0200

- Subject: [PATCH 3/3] core: remove support for ConditionNull=

- 

- The concept is flawed, and mostly useless. Let's finally remove it.

- 

- It has been deprecated since 90a2ec10f2d43a8530aae856013518eb567c4039 (6

- years ago) and we started to warn since

- 55dadc5c57ef1379dbc984938d124508a454be55 (1.5 years ago).

- 

- Let's get rid of it altogether.

- ---

-  man/systemd.unit.xml                          |  3 -

-  src/analyze/analyze-condition.c               |  4 +-

-  src/core/dbus-unit.c                          | 22 +++-----

-  src/core/load-fragment-gperf.gperf.m4         |  2 -

-  src/core/load-fragment.c                      | 55 -------------------

-  src/core/load-fragment.h                      |  1 -

-  src/shared/condition.c                        | 21 +------

-  src/shared/condition.h                        |  2 -

-  src/test/test-condition.c                     | 15 -----

-  .../fuzz-unit-file/systemd-machined.service   |  3 -

-  10 files changed, 11 insertions(+), 117 deletions(-)

- 

- diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml

- index 7ef6080237e..50f35aaa3cc 100644

- --- a/man/systemd.unit.xml

- +++ b/man/systemd.unit.xml

- @@ -1092,9 +1092,6 @@

-        <para>Except for <varname>ConditionPathIsSymbolicLink=</varname>, all path checks follow symlinks.</para>

-  

-        <variablelist class='unit-directives'>

- -        <!-- We do not document ConditionNull= here, as it is not particularly useful and probably just

- -             confusing. -->

- -

-          <varlistentry>

-            <term><varname>ConditionArchitecture=</varname></term>

-  

- diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c

- index 13f75e813a2..e1365e18056 100644

- --- a/src/analyze/analyze-condition.c

- +++ b/src/analyze/analyze-condition.c

- @@ -38,9 +38,7 @@ static int parse_condition(Unit *u, const char *line) {

-  

-                  p += strspn(p, WHITESPACE);

-  

- -                if (t == CONDITION_NULL) /* deprecated, but we should still parse this for now */

- -                        callback = config_parse_unit_condition_null;

- -                else if (condition_takes_path(t))

- +                if (condition_takes_path(t))

-                          callback = config_parse_unit_condition_path;

-                  else

-                          callback = config_parse_unit_condition_string;

- diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c

- index 9e9d3b101e5..e799771c220 100644

- --- a/src/core/dbus-unit.c

- +++ b/src/core/dbus-unit.c

- @@ -1974,14 +1974,11 @@ static int bus_set_transient_conditions(

-                  if (t < 0)

-                          return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name);

-  

- -                if (t != CONDITION_NULL) {

- -                        if (isempty(param))

- -                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);

- +                if (isempty(param))

- +                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name);

-  

- -                        if (condition_takes_path(t) && !path_is_absolute(param))

- -                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);

- -                } else

- -                        param = NULL;

- +                if (condition_takes_path(t) && !path_is_absolute(param))

- +                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param);

-  

-                  if (!UNIT_WRITE_FLAGS_NOOP(flags)) {

-                          Condition *c;

- @@ -1992,14 +1989,9 @@ static int bus_set_transient_conditions(

-  

-                          LIST_PREPEND(conditions, *list, c);

-  

- -                        if (t != CONDITION_NULL)

- -                                unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,

- -                                                    "%s=%s%s%s", type_name,

- -                                                    trigger ? "|" : "", negate ? "!" : "", param);

- -                        else

- -                                unit_write_settingf(u, flags, name,

- -                                                    "%s=%s%s", type_name,

- -                                                    trigger ? "|" : "", yes_no(!negate));

- +                        unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name,

- +                                            "%s=%s%s%s", type_name,

- +                                            trigger ? "|" : "", negate ? "!" : "", param);

-                  }

-  

-                  empty = false;

- diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4

- index 1e6bd6483c2..a191de62af3 100644

- --- a/src/core/load-fragment-gperf.gperf.m4

- +++ b/src/core/load-fragment-gperf.gperf.m4

- @@ -292,7 +292,6 @@ Unit.ConditionEnvironment,       config_parse_unit_condition_string, CONDITION_E

-  Unit.ConditionUser,              config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, conditions)

-  Unit.ConditionGroup,             config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, conditions)

-  Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions)

- -Unit.ConditionNull,              config_parse_unit_condition_null,   0,                             offsetof(Unit, conditions)

-  Unit.AssertPathExists,           config_parse_unit_condition_path,   CONDITION_PATH_EXISTS,         offsetof(Unit, asserts)

-  Unit.AssertPathExistsGlob,       config_parse_unit_condition_path,   CONDITION_PATH_EXISTS_GLOB,    offsetof(Unit, asserts)

-  Unit.AssertPathIsDirectory,      config_parse_unit_condition_path,   CONDITION_PATH_IS_DIRECTORY,   offsetof(Unit, asserts)

- @@ -319,7 +318,6 @@ Unit.AssertEnvironment,          config_parse_unit_condition_string, CONDITION_E

-  Unit.AssertUser,                 config_parse_unit_condition_string, CONDITION_USER,                offsetof(Unit, asserts)

-  Unit.AssertGroup,                config_parse_unit_condition_string, CONDITION_GROUP,               offsetof(Unit, asserts)

-  Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts)

- -Unit.AssertNull,                 config_parse_unit_condition_null,   0,                             offsetof(Unit, asserts)

-  Unit.CollectMode,                config_parse_collect_mode,          0,                             offsetof(Unit, collect_mode)

-  m4_dnl

-  Service.PIDFile,                 config_parse_pid_file,              0,                             offsetof(Service, pid_file)

- diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c

- index 266382c84c7..cfd04f3b49f 100644

- --- a/src/core/load-fragment.c

- +++ b/src/core/load-fragment.c

- @@ -2999,60 +2999,6 @@ int config_parse_unit_condition_string(

-          return 0;

-  }

-  

- -int config_parse_unit_condition_null(

- -                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) {

- -

- -        Condition **list = data, *c;

- -        bool trigger, negate;

- -        int b;

- -

- -        assert(filename);

- -        assert(lvalue);

- -        assert(rvalue);

- -        assert(data);

- -

- -        log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue);

- -

- -        if (isempty(rvalue)) {

- -                /* Empty assignment resets the list */

- -                *list = condition_free_list(*list);

- -                return 0;

- -        }

- -

- -        trigger = rvalue[0] == '|';

- -        if (trigger)

- -                rvalue++;

- -

- -        negate = rvalue[0] == '!';

- -        if (negate)

- -                rvalue++;

- -

- -        b = parse_boolean(rvalue);

- -        if (b < 0) {

- -                log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);

- -                return 0;

- -        }

- -

- -        if (!b)

- -                negate = !negate;

- -

- -        c = condition_new(CONDITION_NULL, NULL, trigger, negate);

- -        if (!c)

- -                return log_oom();

- -

- -        LIST_PREPEND(conditions, *list, c);

- -        return 0;

- -}

- -

-  int config_parse_unit_requires_mounts_for(

-                  const char *unit,

-                  const char *filename,

- @@ -5266,7 +5212,6 @@ void unit_dump_config_items(FILE *f) {

-                  { config_parse_ip_tos,                "TOS" },

-                  { config_parse_unit_condition_path,   "CONDITION" },

-                  { config_parse_unit_condition_string, "CONDITION" },

- -                { config_parse_unit_condition_null,   "CONDITION" },

-                  { config_parse_unit_slice,            "SLICE" },

-                  { config_parse_documentation,         "URL" },

-                  { config_parse_service_timeout,       "SECONDS" },

- diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h

- index 2672db5ace2..cee5717d0fb 100644

- --- a/src/core/load-fragment.h

- +++ b/src/core/load-fragment.h

- @@ -58,7 +58,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file);

-  CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos);

-  CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path);

-  CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string);

- -CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null);

-  CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode);

-  CONFIG_PARSER_PROTOTYPE(config_parse_notify_access);

-  CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action);

- diff --git a/src/shared/condition.c b/src/shared/condition.c

- index bf3b5fa1622..1f6105622a5 100644

- --- a/src/shared/condition.c

- +++ b/src/shared/condition.c

- @@ -52,7 +52,7 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger

-  

-          assert(type >= 0);

-          assert(type < _CONDITION_TYPE_MAX);

- -        assert((!parameter) == (type == CONDITION_NULL));

- +        assert(parameter);

-  

-          c = new(Condition, 1);

-          if (!c)

- @@ -776,15 +776,6 @@ static int condition_test_file_is_executable(Condition *c, char **env) {

-                  (st.st_mode & 0111));

-  }

-  

- -static int condition_test_null(Condition *c, char **env) {

- -        assert(c);

- -        assert(c->type == CONDITION_NULL);

- -

- -        /* Note that during parsing we already evaluate the string and

- -         * store it in c->negate */

- -        return true;

- -}

- -

-  int condition_test(Condition *c, char **env) {

-  

-          static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = {

- @@ -811,7 +802,6 @@ int condition_test(Condition *c, char **env) {

-                  [CONDITION_USER]                     = condition_test_user,

-                  [CONDITION_GROUP]                    = condition_test_group,

-                  [CONDITION_CONTROL_GROUP_CONTROLLER] = condition_test_control_group_controller,

- -                [CONDITION_NULL]                     = condition_test_null,

-                  [CONDITION_CPUS]                     = condition_test_cpus,

-                  [CONDITION_MEMORY]                   = condition_test_memory,

-                  [CONDITION_ENVIRONMENT]              = condition_test_environment,

- @@ -859,23 +849,20 @@ bool condition_test_list(

-                  r = condition_test(c, env);

-  

-                  if (logger) {

- -                        const char *p = c->type == CONDITION_NULL ? "true" : c->parameter;

- -                        assert(p);

- -

-                          if (r < 0)

-                                  logger(userdata, LOG_WARNING, r, PROJECT_FILE, __LINE__, __func__,

-                                         "Couldn't determine result for %s=%s%s%s, assuming failed: %m",

-                                         to_string(c->type),

-                                         c->trigger ? "|" : "",

-                                         c->negate ? "!" : "",

- -                                       p);

- +                                       c->parameter);

-                          else

-                                  logger(userdata, LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__,

-                                         "%s=%s%s%s %s.",

-                                         to_string(c->type),

-                                         c->trigger ? "|" : "",

-                                         c->negate ? "!" : "",

- -                                       p,

- +                                       c->parameter,

-                                         condition_result_to_string(c->result));

-                  }

-  

- @@ -937,7 +924,6 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = {

-          [CONDITION_USER] = "ConditionUser",

-          [CONDITION_GROUP] = "ConditionGroup",

-          [CONDITION_CONTROL_GROUP_CONTROLLER] = "ConditionControlGroupController",

- -        [CONDITION_NULL] = "ConditionNull",

-          [CONDITION_CPUS] = "ConditionCPUs",

-          [CONDITION_MEMORY] = "ConditionMemory",

-          [CONDITION_ENVIRONMENT] = "ConditionEnvironment",

- @@ -969,7 +955,6 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = {

-          [CONDITION_USER] = "AssertUser",

-          [CONDITION_GROUP] = "AssertGroup",

-          [CONDITION_CONTROL_GROUP_CONTROLLER] = "AssertControlGroupController",

- -        [CONDITION_NULL] = "AssertNull",

-          [CONDITION_CPUS] = "AssertCPUs",

-          [CONDITION_MEMORY] = "AssertMemory",

-          [CONDITION_ENVIRONMENT] = "AssertEnvironment",

- diff --git a/src/shared/condition.h b/src/shared/condition.h

- index fea74d228d8..e5ad43f945b 100644

- --- a/src/shared/condition.h

- +++ b/src/shared/condition.h

- @@ -34,8 +34,6 @@ typedef enum ConditionType {

-          CONDITION_FILE_NOT_EMPTY,

-          CONDITION_FILE_IS_EXECUTABLE,

-  

- -        CONDITION_NULL,

- -

-          CONDITION_USER,

-          CONDITION_GROUP,

-  

- diff --git a/src/test/test-condition.c b/src/test/test-condition.c

- index ddf2e669c03..d209c1304c8 100644

- --- a/src/test/test-condition.c

- +++ b/src/test/test-condition.c

- @@ -438,20 +438,6 @@ static void test_condition_test_kernel_version(void) {

-          condition_free(condition);

-  }

-  

- -static void test_condition_test_null(void) {

- -        Condition *condition;

- -

- -        condition = condition_new(CONDITION_NULL, NULL, false, false);

- -        assert_se(condition);

- -        assert_se(condition_test(condition, environ) > 0);

- -        condition_free(condition);

- -

- -        condition = condition_new(CONDITION_NULL, NULL, false, true);

- -        assert_se(condition);

- -        assert_se(condition_test(condition, environ) == 0);

- -        condition_free(condition);

- -}

- -

-  static void test_condition_test_security(void) {

-          Condition *condition;

-  

- @@ -868,7 +854,6 @@ int main(int argc, char *argv[]) {

-          test_condition_test_architecture();

-          test_condition_test_kernel_command_line();

-          test_condition_test_kernel_version();

- -        test_condition_test_null();

-          test_condition_test_security();

-          print_securities();

-          test_condition_test_virtualization();

- diff --git a/test/fuzz/fuzz-unit-file/systemd-machined.service b/test/fuzz/fuzz-unit-file/systemd-machined.service

- index 70b627c5f40..79ee9861d8e 100644

- --- a/test/fuzz/fuzz-unit-file/systemd-machined.service

- +++ b/test/fuzz/fuzz-unit-file/systemd-machined.service

- @@ -15,9 +15,6 @@ Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined

-  Wants=machine.slice

-  After=machine.slice

-  RequiresMountsFor=/var/lib/machines

- -ConditionNull=true

- -ConditionNull=

- -ConditionNull=|!false

-  OnFailureIsolate=false

-  FailureActionExitStatus=222

-  FailureActionExitStatus=

@@ -1,108 +0,0 @@ 

- From 3335de91437bc983c95cfab86489ceb3a0b0a6aa Mon Sep 17 00:00:00 2001

- From: Chris Down <chris@chrisdown.name>

- Date: Tue, 25 Aug 2020 21:59:11 +0100

- Subject: [PATCH 1/2] path: Skip directories when finalising $PATH search

- 

- Imagine $PATH /a:/b. There is an echo command at /b/echo. Under this

- configuration, this works fine:

- 

-     % systemd-run --user --scope echo .

-     Running scope as unit: run-rfe98e0574b424d63a641644af511ff30.scope

-     .

- 

- However, if I do `mkdir /a/echo`, this happens:

- 

-     % systemd-run --user --scope echo .

-     Running scope as unit: run-rcbe9369537ed47f282ee12ce9f692046.scope

-     Failed to execute: Permission denied

- 

- We check whether the resulting file is executable for the performing

- user, but of course, most directories are anyway, since that's needed to

- list within it. As such, another is_dir() check is needed prior to

- considering the search result final.

- 

- Another approach might be to check S_ISREG, but there may be more gnarly

- edge cases there than just eliminating this obviously pathological

- example, so let's just do this for now.

- ---

-  src/basic/path-util.c | 3 +++

-  1 file changed, 3 insertions(+)

- 

- diff --git a/src/basic/path-util.c b/src/basic/path-util.c

- index c4e022b3a1..d3b4978239 100644

- --- a/src/basic/path-util.c

- +++ b/src/basic/path-util.c

- @@ -637,6 +637,9 @@ int find_binary(const char *name, char **ret) {

-                  if (!j)

-                          return -ENOMEM;

-  

- +                if (is_dir(j, true))

- +                        continue;

- +

-                  if (access(j, X_OK) >= 0) {

-                          /* Found it! */

-  

- -- 

- 2.26.2

- 

- 

- From 2f94890f37c13dcd680a63876ed6d34f8e66d0a3 Mon Sep 17 00:00:00 2001

- From: Chris Down <chris@chrisdown.name>

- Date: Wed, 26 Aug 2020 18:49:27 +0100

- Subject: [PATCH 2/2] path: Improve $PATH search directory case

- 

- Previously:

- 

- 1. last_error wouldn't be updated with errors from is_dir;

- 2. We'd always issue a stat(), even for binaries without execute;

- 3. We used stat() instead of access(), which is cheaper.

- 

- This change avoids all of those, by only checking inside X_OK-positive

- case whether access() works on the path with an extra slash appended.

- Thanks to Lennart for the suggestion.

- ---

-  src/basic/path-util.c | 25 ++++++++++++++++++-------

-  1 file changed, 18 insertions(+), 7 deletions(-)

- 

- diff --git a/src/basic/path-util.c b/src/basic/path-util.c

- index d3b4978239..7b0863f749 100644

- --- a/src/basic/path-util.c

- +++ b/src/basic/path-util.c

- @@ -637,16 +637,27 @@ int find_binary(const char *name, char **ret) {

-                  if (!j)

-                          return -ENOMEM;

-  

- -                if (is_dir(j, true))

- -                        continue;

- -

-                  if (access(j, X_OK) >= 0) {

- -                        /* Found it! */

- +                        _cleanup_free_ char *with_dash;

-  

- -                        if (ret)

- -                                *ret = path_simplify(TAKE_PTR(j), false);

- +                        with_dash = strjoin(j, "/");

- +                        if (!with_dash)

- +                                return -ENOMEM;

-  

- -                        return 0;

- +                        /* If this passes, it must be a directory, and so should be skipped. */

- +                        if (access(with_dash, X_OK) >= 0)

- +                                continue;

- +

- +                        /**

- +                         * We can't just `continue` inverting this case, since we need to update last_error.

- +                         */

- +                        if (errno == ENOTDIR) {

- +                                /* Found it! */

- +                                if (ret)

- +                                        *ret = path_simplify(TAKE_PTR(j), false);

- +

- +                                return 0;

- +                        }

-                  }

-  

-                  /* PATH entries which we don't have access to are ignored, as per tradition. */

- -- 

- 2.26.2

- 

@@ -1,317 +0,0 @@ 

- From 056799e2e147d678e156c5a1fce15b04762f1313 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Tue, 1 Sep 2020 23:50:01 +0200

- Subject: [PATCH 1/3] core/socket: we may get ENOTCONN from

-  socket_instantiate_service()

- 

- This means that the connection was aborted before we even got to figure out

- what the service name will be. Let's treat this as a non-event and close the

- connection fd without any further messages.

- 

- Code last changed in 934ef6a5.

- Reported-by: Thiago Macieira <thiago.macieira@intel.com>

- 

- With the patch:

- systemd[1]: foobar.socket: Incoming traffic

- systemd[1]: foobar.socket: Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.

- ...

- 

- Also, when we get ENOMEM, don't give the hint about missing unit.

- ---

-  src/core/socket.c | 35 ++++++++++++++++++++++++-----------

-  1 file changed, 24 insertions(+), 11 deletions(-)

- 

- diff --git a/src/core/socket.c b/src/core/socket.c

- index ebf5ce3b16..f880040331 100644

- --- a/src/core/socket.c

- +++ b/src/core/socket.c

- @@ -18,6 +18,7 @@

-  #include "dbus-socket.h"

-  #include "dbus-unit.h"

-  #include "def.h"

- +#include "errno-list.h"

-  #include "exit-status.h"

-  #include "fd-util.h"

-  #include "format-util.h"

- @@ -1418,11 +1419,12 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) {

-  

-          if (cfd >= 0) {

-                  r = instance_from_socket(cfd, s->n_accepted, &instance);

- -                if (r == -ENOTCONN)

- -                        /* ENOTCONN is legitimate if TCP RST was received.

- -                         * This connection is over, but the socket unit lives on. */

- +                if (ERRNO_IS_DISCONNECT(r))

- +                        /* ENOTCONN is legitimate if TCP RST was received. Other socket families might return

- +                         * different errors. This connection is over, but the socket unit lives on. */

-                          return log_unit_debug_errno(UNIT(s), r,

- -                                                    "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring.");

- +                                                    "Got %s on incoming socket, assuming aborted connection attempt, ignoring.",

- +                                                    errno_to_name(r));

-                  if (r < 0)

-                          return r;

-          }

- @@ -2359,8 +2361,8 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-                  if (!pending) {

-                          if (!UNIT_ISSET(s->service)) {

- -                                log_unit_error(UNIT(s), "Service to activate vanished, refusing activation.");

- -                                r = -ENOENT;

- +                                r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT),

- +                                                         "Service to activate vanished, refusing activation.");

-                                  goto fail;

-                          }

-  

- @@ -2382,8 +2384,10 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-                  if (s->max_connections_per_source > 0) {

-                          r = socket_acquire_peer(s, cfd, &p);

- -                        if (r < 0)

- -                                goto refuse;

- +                        if (ERRNO_IS_DISCONNECT(r))

- +                                goto notconn;

- +                        if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */

- +                                goto fail;

-                          if (r > 0 && p->n_ref > s->max_connections_per_source) {

-                                  _cleanup_free_ char *t = NULL;

-  

- @@ -2397,6 +2401,8 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  }

-  

-                  r = socket_instantiate_service(s, cfd);

- +                if (ERRNO_IS_DISCONNECT(r))

- +                        goto notconn;

-                  if (r < 0)

-                          goto fail;

-  

- @@ -2406,6 +2412,8 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  s->n_accepted++;

-  

-                  r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net);

- +                if (ERRNO_IS_DISCONNECT(r))

- +                        goto notconn;

-                  if (r < 0)

-                          goto fail;

-  

- @@ -2430,13 +2438,18 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-  refuse:

-          s->n_refused++;

- +notconn:

-          safe_close(cfd);

-          return;

-  

-  fail:

- -        log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",

- -                         cfd >= 0 ? "template" : "non-template",

- -                         bus_error_message(&error, r));

- +        if (ERRNO_IS_RESOURCE(r))

- +                log_unit_warning(UNIT(s), "Failed to queue service startup job: %s",

- +                                 bus_error_message(&error, r));

- +        else

- +                log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s",

- +                                 cfd >= 0 ? "template" : "non-template",

- +                                 bus_error_message(&error, r));

-  

-          socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);

-          safe_close(cfd);

- -- 

- 2.26.2

- 

- 

- From 86f9af3eb8bea0bea86bb027cb341e6b13beecb5 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Wed, 2 Sep 2020 18:04:10 +0200

- Subject: [PATCH 2/3] core/socket: fold socket_instantiate_service() into

-  socket_enter_running()

- 

- socket_instantiate_service() was doing unit_ref_set(), and the caller was

- immediately doing unit_ref_unset(). After we get rid of this, it doesn't seem

- worth it to have two functions.

- ---

-  src/core/socket.c | 39 ++++++++++-----------------------------

-  1 file changed, 10 insertions(+), 29 deletions(-)

- 

- diff --git a/src/core/socket.c b/src/core/socket.c

- index f880040331..5e128d9fef 100644

- --- a/src/core/socket.c

- +++ b/src/core/socket.c

- @@ -206,27 +206,6 @@ static int socket_arm_timer(Socket *s, usec_t usec) {

-          return 0;

-  }

-  

- -static int socket_instantiate_service(Socket *s, int cfd) {

- -        Unit *service;

- -        int r;

- -

- -        assert(s);

- -        assert(cfd >= 0);

- -

- -        /* This fills in s->service if it isn't filled in yet. For Accept=yes sockets we create the next

- -         * connection service here. For Accept=no this is mostly a NOP since the service is figured out at

- -         * load time anyway. */

- -

- -        r = socket_load_service_unit(s, cfd, &service);

- -        if (r < 0)

- -                return r;

- -

- -        unit_ref_set(&s->service, UNIT(s), service);

- -

- -        return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service,

- -                                         false, UNIT_DEPENDENCY_IMPLICIT);

- -}

- -

-  static bool have_non_accept_socket(Socket *s) {

-          SocketPort *p;

-  

- @@ -2374,7 +2353,7 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  socket_set_state(s, SOCKET_RUNNING);

-          } else {

-                  _cleanup_(socket_peer_unrefp) SocketPeer *p = NULL;

- -                Service *service;

- +                Unit *service;

-  

-                  if (s->n_connections >= s->max_connections) {

-                          log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.",

- @@ -2400,18 +2379,20 @@ static void socket_enter_running(Socket *s, int cfd) {

-                          }

-                  }

-  

- -                r = socket_instantiate_service(s, cfd);

- +                r = socket_load_service_unit(s, cfd, &service);

-                  if (ERRNO_IS_DISCONNECT(r))

-                          goto notconn;

-                  if (r < 0)

-                          goto fail;

-  

- -                service = SERVICE(UNIT_DEREF(s->service));

- -                unit_ref_unset(&s->service);

- +                r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service,

- +                                              false, UNIT_DEPENDENCY_IMPLICIT);

- +                if (r < 0)

- +                        goto fail;

-  

-                  s->n_accepted++;

-  

- -                r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net);

- +                r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net);

-                  if (ERRNO_IS_DISCONNECT(r))

-                          goto notconn;

-                  if (r < 0)

- @@ -2420,13 +2401,13 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */

-                  s->n_connections++;

-  

- -                service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */

- +                SERVICE(service)->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */

-  

- -                r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, NULL, &error, NULL);

- +                r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL);

-                  if (r < 0) {

-                          /* We failed to activate the new service, but it still exists. Let's make sure the

-                           * service closes and forgets the connection fd again, immediately. */

- -                        service_close_socket_fd(service);

- +                        service_close_socket_fd(SERVICE(service));

-                          goto fail;

-                  }

-  

- -- 

- 2.26.2

- 

- 

- From b7e9403a4c6220478980555ef40905d030b307f5 Mon Sep 17 00:00:00 2001

- From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

- Date: Wed, 2 Sep 2020 18:17:14 +0200

- Subject: [PATCH 3/3] core/socket: use _cleanup_ to close the connection fd

- 

- Removing the gotos would lead to a lot of duplicated code, so I left them

- as they were.

- ---

-  src/core/socket.c | 22 ++++++++++------------

-  1 file changed, 10 insertions(+), 12 deletions(-)

- 

- diff --git a/src/core/socket.c b/src/core/socket.c

- index 5e128d9fef..a77a297cf5 100644

- --- a/src/core/socket.c

- +++ b/src/core/socket.c

- @@ -2296,13 +2296,14 @@ static void flush_ports(Socket *s) {

-          }

-  }

-  

- -static void socket_enter_running(Socket *s, int cfd) {

- +static void socket_enter_running(Socket *s, int cfd_in) {

- +        /* Note that this call takes possession of the connection fd passed. It either has to assign it

- +         * somewhere or close it. */

- +        _cleanup_close_ int cfd = cfd_in;

- +

-          _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;

-          int r;

-  

- -        /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or

- -         * close it. */

- -

-          assert(s);

-  

-          /* We don't take connections anymore if we are supposed to shut down anyway */

- @@ -2312,9 +2313,8 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-                  if (cfd >= 0)

-                          goto refuse;

- -                else

- -                        flush_ports(s);

-  

- +                flush_ports(s);

-                  return;

-          }

-  

- @@ -2364,7 +2364,7 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  if (s->max_connections_per_source > 0) {

-                          r = socket_acquire_peer(s, cfd, &p);

-                          if (ERRNO_IS_DISCONNECT(r))

- -                                goto notconn;

- +                                return;

-                          if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */

-                                  goto fail;

-                          if (r > 0 && p->n_ref > s->max_connections_per_source) {

- @@ -2381,7 +2381,7 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-                  r = socket_load_service_unit(s, cfd, &service);

-                  if (ERRNO_IS_DISCONNECT(r))

- -                        goto notconn;

- +                        return;

-                  if (r < 0)

-                          goto fail;

-  

- @@ -2394,7 +2394,7 @@ static void socket_enter_running(Socket *s, int cfd) {

-  

-                  r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net);

-                  if (ERRNO_IS_DISCONNECT(r))

- -                        goto notconn;

- +                        return;

-                  if (r < 0)

-                          goto fail;

-  

- @@ -2415,12 +2415,11 @@ static void socket_enter_running(Socket *s, int cfd) {

-                  unit_add_to_dbus_queue(UNIT(s));

-          }

-  

- +        TAKE_FD(cfd);

-          return;

-  

-  refuse:

-          s->n_refused++;

- -notconn:

- -        safe_close(cfd);

-          return;

-  

-  fail:

- @@ -2433,7 +2432,6 @@ fail:

-                                   bus_error_message(&error, r));

-  

-          socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES);

- -        safe_close(cfd);

-  }

-  

-  static void socket_run_next(Socket *s) {

- -- 

- 2.26.2

- 

@@ -1,233 +0,0 @@ 

- From 7a481a17ad01c7be526829a835f7da3d6b71577f Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Fri, 11 Sep 2020 19:49:33 +0200

- Subject: [PATCH 1/3] core: propagate triggered unit in more load states

- 

- In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating

- triggered unit state to the triggering unit for service units in more

- load states, so that we don't accidentally stop tracking state

- correctly.

- 

- Do the same for our other triggering unit states: automounts, paths, and

- timers.

- 

- Also, make this an assertion rather than a simple test. After all it

- should never happen that we get called for half-loaded units or units of

- the wrong type. The load routines should already have made this

- impossible.

- ---

-  src/core/automount.c   | 4 ++--

-  src/core/path.c        | 7 +++----

-  src/core/socket.c      | 9 ++-------

-  src/core/timer.c       | 4 ++--

-  src/core/transaction.c | 2 +-

-  src/core/unit.h        | 4 ++++

-  6 files changed, 14 insertions(+), 16 deletions(-)

- 

- diff --git a/src/core/automount.c b/src/core/automount.c

- index 1f05198766..73f0fb8c71 100644

- --- a/src/core/automount.c

- +++ b/src/core/automount.c

- @@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {

-          assert(other);

-  

-          /* Filter out invocations with bogus state */

- -        if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)

- -                return;

- +        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));

- +        assert(other->type == UNIT_MOUNT);

-  

-          /* Don't propagate state changes from the mount if we are already down */

-          if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))

- diff --git a/src/core/path.c b/src/core/path.c

- index 1c3c28e341..8ffec72ede 100644

- --- a/src/core/path.c

- +++ b/src/core/path.c

- @@ -748,11 +748,10 @@ static void path_trigger_notify(Unit *u, Unit *other) {

-          assert(u);

-          assert(other);

-  

- -        /* Invoked whenever the unit we trigger changes state or gains

- -         * or loses a job */

- +        /* Invoked whenever the unit we trigger changes state or gains or loses a job */

-  

- -        if (other->load_state != UNIT_LOADED)

- -                return;

- +        /* Filter out invocations with bogus state */

- +        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));

-  

-          if (p->state == PATH_RUNNING &&

-              UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {

- diff --git a/src/core/socket.c b/src/core/socket.c

- index 127195c9fe..ebf5ce3b16 100644

- --- a/src/core/socket.c

- +++ b/src/core/socket.c

- @@ -3274,13 +3274,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {

-          assert(other);

-  

-          /* Filter out invocations with bogus state */

- -        if (!IN_SET(other->load_state,

- -                    UNIT_LOADED,

- -                    UNIT_NOT_FOUND,

- -                    UNIT_BAD_SETTING,

- -                    UNIT_ERROR,

- -                    UNIT_MASKED) || other->type != UNIT_SERVICE)

- -                return;

- +        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));

- +        assert(other->type == UNIT_SERVICE);

-  

-          /* Don't propagate state changes from the service if we are already down */

-          if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))

- diff --git a/src/core/timer.c b/src/core/timer.c

- index 03a9c14f76..94388f0727 100644

- --- a/src/core/timer.c

- +++ b/src/core/timer.c

- @@ -746,8 +746,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {

-          assert(u);

-          assert(other);

-  

- -        if (other->load_state != UNIT_LOADED)

- -                return;

- +        /* Filter out invocations with bogus state */

- +        assert(UNIT_IS_LOAD_COMPLETE(other->load_state));

-  

-          /* Reenable all timers that depend on unit state */

-          LIST_FOREACH(value, v, t->values)

- diff --git a/src/core/transaction.c b/src/core/transaction.c

- index 0fa419787e..befac19788 100644

- --- a/src/core/transaction.c

- +++ b/src/core/transaction.c

- @@ -949,7 +949,7 @@ int transaction_add_job_and_dependencies(

-  

-          /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set

-           * temporarily. */

- -        if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))

- +        if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))

-                  return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);

-  

-          if (type != JOB_STOP) {

- diff --git a/src/core/unit.h b/src/core/unit.h

- index 4130cd50a9..ae2ce74243 100644

- --- a/src/core/unit.h

- +++ b/src/core/unit.h

- @@ -49,6 +49,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {

-          return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);

-  }

-  

- +static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {

- +        return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;

- +}

- +

-  /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We

-   * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be

-   * created as a result of multiple "reasons", hence the bitmask. */

- -- 

- 2.26.2

- 

- 

- From 6b083e21c2bfdba79d43d5d56f02dc795dae9368 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Fri, 11 Sep 2020 19:57:09 +0200

- Subject: [PATCH 2/3] core: propagate unit start limit hit state to triggering

-  path unit

- 

- We already do this for socket and automount units, do it for path units

- too: if the triggered service keeps hitting the start limit, then fail

- the triggering unit too, so that we don#t busy loop forever.

- 

- (Note that this leaves only timer units out in the cold for this kind of

- protection, but it shouldn't matter there, as they are naturally

- protected against busy loops: they are scheduled by time anyway).

- 

- Fixes: #16669

- ---

-  src/core/path.c | 15 +++++++++++++++

-  src/core/path.h |  1 +

-  2 files changed, 16 insertions(+)

- 

- diff --git a/src/core/path.c b/src/core/path.c

- index 8ffec72ede..4f4e7100cf 100644

- --- a/src/core/path.c

- +++ b/src/core/path.c

- @@ -753,6 +753,20 @@ static void path_trigger_notify(Unit *u, Unit *other) {

-          /* Filter out invocations with bogus state */

-          assert(UNIT_IS_LOAD_COMPLETE(other->load_state));

-  

- +        /* Don't propagate state changes from the triggered unit if we are already down */

- +        if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))

- +                return;

- +

- +        /* Propagate start limit hit state */

- +        if (other->start_limit_hit) {

- +                path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT);

- +                return;

- +        }

- +

- +        /* Don't propagate anything if there's still a job queued */

- +        if (other->job)

- +                return;

- +

-          if (p->state == PATH_RUNNING &&

-              UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {

-                  log_unit_debug(UNIT(p), "Got notified about unit deactivation.");

- @@ -789,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {

-          [PATH_SUCCESS] = "success",

-          [PATH_FAILURE_RESOURCES] = "resources",

-          [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",

- +        [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",

-  };

-  

-  DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);

- diff --git a/src/core/path.h b/src/core/path.h

- index 9e2836535a..4043650fe0 100644

- --- a/src/core/path.h

- +++ b/src/core/path.h

- @@ -45,6 +45,7 @@ typedef enum PathResult {

-          PATH_SUCCESS,

-          PATH_FAILURE_RESOURCES,

-          PATH_FAILURE_START_LIMIT_HIT,

- +        PATH_FAILURE_UNIT_START_LIMIT_HIT,

-          _PATH_RESULT_MAX,

-          _PATH_RESULT_INVALID = -1

-  } PathResult;

- -- 

- 2.26.2

- 

- 

- From 32c556c612ff38b09fe7d14d1840aceb2d76360d Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Mon, 14 Sep 2020 12:59:38 +0200

- Subject: [PATCH 3/3] unit-def: drop pointless 0 initialization of first enum

-  value

- 

- This is implied in C and we generally don't bother with this, so don't

- bother with this here either.

- ---

-  src/basic/unit-def.h | 4 ++--

-  1 file changed, 2 insertions(+), 2 deletions(-)

- 

- diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h

- index 53419ecd8a..1fab6c78ab 100644

- --- a/src/basic/unit-def.h

- +++ b/src/basic/unit-def.h

- @@ -9,7 +9,7 @@

-   * when other criteria (cpu weight, nice level) are identical.

-   * In this case service units have the highest priority. */

-  typedef enum UnitType {

- -        UNIT_SERVICE = 0,

- +        UNIT_SERVICE,

-          UNIT_MOUNT,

-          UNIT_SWAP,

-          UNIT_SOCKET,

- @@ -25,7 +25,7 @@ typedef enum UnitType {

-  } UnitType;

-  

-  typedef enum UnitLoadState {

- -        UNIT_STUB = 0,

- +        UNIT_STUB,

-          UNIT_LOADED,

-          UNIT_NOT_FOUND,    /* error condition #1: unit file not found */

-          UNIT_BAD_SETTING,  /* error condition #2: we couldn't parse some essential unit file setting */

- -- 

- 2.26.2

- 

@@ -1,316 +0,0 @@ 

- From 0ead15331dc9414e7d4b3f0b96ed1908ceaf8f8b Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Wed, 16 Sep 2020 22:11:48 +0200

- Subject: [PATCH 1/5] nspawn: check return of setsid()

- 

- Let's verify that everything works the way we expect it to work, hence

- check setsid() return code.

- ---

-  src/nspawn/nspawn-stub-pid1.c | 5 ++++-

-  1 file changed, 4 insertions(+), 1 deletion(-)

- 

- diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c

- index d86dd23185..f785a3b248 100644

- --- a/src/nspawn/nspawn-stub-pid1.c

- +++ b/src/nspawn/nspawn-stub-pid1.c

- @@ -66,7 +66,10 @@ int stub_pid1(sd_id128_t uuid) {

-          if (pid == 0) {

-                  /* Return in the child */

-                  assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);

- -                setsid();

- +

- +                if (setsid() < 0)

- +                        return log_error_errno(errno, "Failed to become session leader in payload process: %m");

- +

-                  return 0;

-          }

-  

- -- 

- 2.26.2

- 

- 

- From b4fa908fbdcbcf01c96e983460689800b8bb76af Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Wed, 16 Sep 2020 22:12:29 +0200

- Subject: [PATCH 2/5] nspawn: print log notice when we are invoked from a tty

-  but in "pipe" mode

- 

- If people do this then things are weird, and they should probably use

- --console=interactive (i.e. the default) instead.

- 

- Prompted-by: #17070

- ---

-  src/nspawn/nspawn.c | 10 ++++++++--

-  1 file changed, 8 insertions(+), 2 deletions(-)

- 

- diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c

- index 3b9493f232..efc541f512 100644

- --- a/src/nspawn/nspawn.c

- +++ b/src/nspawn/nspawn.c

- @@ -272,9 +272,15 @@ static int handle_arg_console(const char *arg) {

-                  arg_console_mode = CONSOLE_READ_ONLY;

-          else if (streq(arg, "passive"))

-                  arg_console_mode = CONSOLE_PASSIVE;

- -        else if (streq(arg, "pipe"))

- +        else if (streq(arg, "pipe")) {

- +                if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)

- +                        log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE,

- +                                 "Console mode 'pipe' selected, but standard input/output are connected to an interactive TTY. "

- +                                 "Most likely you want to use 'interactive' console mode for proper interactivity and shell job control. "

- +                                 "Proceeding anyway.");

- +

-                  arg_console_mode = CONSOLE_PIPE;

- -        else

- +        } else

-                  return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);

-  

-          arg_settings_mask |= SETTING_CONSOLE_MODE;

- -- 

- 2.26.2

- 

- 

- From 19db1706dadcec4f4c44f9abf8dc33a336f93326 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Wed, 16 Sep 2020 22:16:10 +0200

- Subject: [PATCH 3/5] nspawn: fix fd leak on failure path

- 

- ---

-  src/nspawn/nspawn.c | 3 ++-

-  1 file changed, 2 insertions(+), 1 deletion(-)

- 

- diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c

- index efc541f512..15dbdbe738 100644

- --- a/src/nspawn/nspawn.c

- +++ b/src/nspawn/nspawn.c

- @@ -2178,7 +2178,7 @@ static int setup_pts(const char *dest) {

-  }

-  

-  static int setup_stdio_as_dev_console(void) {

- -        int terminal;

- +        _cleanup_close_ int terminal = -1;

-          int r;

-  

-          terminal = open_terminal("/dev/console", O_RDWR);

- @@ -2193,6 +2193,7 @@ static int setup_stdio_as_dev_console(void) {

-  

-          /* invalidates 'terminal' on success and failure */

-          r = rearrange_stdio(terminal, terminal, terminal);

- +        TAKE_FD(terminal);

-          if (r < 0)

-                  return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");

-  

- -- 

- 2.26.2

- 

- 

- From d297a871ef720227af845fe8b0f1e0fe7560b433 Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Wed, 16 Sep 2020 22:34:43 +0200

- Subject: [PATCH 4/5] nspawn: don't become TTY controller just to undo it later

-  again

- 

- Instead of first becoming a controlling process of the payload pty

- as side effect of opening it (without O_NOCTTY), and then possibly

- dropping it again, let's do it cleanly an reverse the logic: let's open

- the pty without becoming its controller first. Only after everything

- went the way we wanted it to go become the controller explicitly.

- 

- This has the benefit that the PID 1 stub process we run (as effect of

- --as-pid2) doesn't have to lose the tty explicitly, but can just

- continue running with things. And we explicitly make the tty controlling

- right before invoking actual payload.

- 

- In order to make sure everything works as expected validate that the

- stub PID 1 in the container really has no conrolling tty by issuing the

- TIOCNOTTY tty and expecting ENOTTY, and log about it.

- 

- This shouldn't change behaviour much, it just makes thins a bit cleaner,

- in particular as we'll not trigger SIGHUP on ourselves (since we are

- controller and session leader) due to TIOCNOTTY which we then have to

- explicitly ignore.

- ---

-  src/nspawn/nspawn-stub-pid1.c | 12 ++++++------

-  src/nspawn/nspawn.c           | 16 +++++++++++++---

-  2 files changed, 19 insertions(+), 9 deletions(-)

- 

- diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c

- index f785a3b248..60d7439fb1 100644

- --- a/src/nspawn/nspawn-stub-pid1.c

- +++ b/src/nspawn/nspawn-stub-pid1.c

- @@ -53,12 +53,6 @@ int stub_pid1(sd_id128_t uuid) {

-          assert_se(sigfillset(&fullmask) >= 0);

-          assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);

-  

- -        /* Surrender the terminal this stub may control so that child processes can have a controlling terminal

- -         * without resorting to setsid hacks. */

- -        r = ioctl(STDIN_FILENO, TIOCNOTTY);

- -        if (r < 0 && errno != ENOTTY)

- -                return log_error_errno(errno, "Failed to surrender controlling terminal: %m");

- -

-          pid = fork();

-          if (pid < 0)

-                  return log_error_errno(errno, "Failed to fork child pid: %m");

- @@ -79,6 +73,12 @@ int stub_pid1(sd_id128_t uuid) {

-          (void) close_all_fds(NULL, 0);

-          log_open();

-  

- +        if (ioctl(STDIN_FILENO, TIOCNOTTY) < 0) {

- +                if (errno != ENOTTY)

- +                        log_warning_errno(errno, "Unexpected error from TIOCNOTTY ioctl in init stub process, ignoring: %m");

- +        } else

- +                log_warning("Expected TIOCNOTTY to fail, but it succeeded in init stub process, ignoring.");

- +

-          /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,

-           * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ

-           * find them set. */

- diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c

- index 15dbdbe738..783147f122 100644

- --- a/src/nspawn/nspawn.c

- +++ b/src/nspawn/nspawn.c

- @@ -11,10 +11,12 @@

-  #endif

-  #include <stdlib.h>

-  #include <sys/file.h>

- +#include <sys/ioctl.h>

-  #include <sys/personality.h>

-  #include <sys/prctl.h>

-  #include <sys/types.h>

-  #include <sys/wait.h>

- +#include <termios.h>

-  #include <unistd.h>

-  

-  #include "sd-bus.h"

- @@ -2181,7 +2183,9 @@ static int setup_stdio_as_dev_console(void) {

-          _cleanup_close_ int terminal = -1;

-          int r;

-  

- -        terminal = open_terminal("/dev/console", O_RDWR);

- +        /* We open the TTY in O_NOCTTY mode, so that we do not become controller yet. We'll do that later

- +         * explicitly, if we are configured to. */

- +        terminal = open_terminal("/dev/console", O_RDWR|O_NOCTTY);

-          if (terminal < 0)

-                  return log_error_errno(terminal, "Failed to open console: %m");

-  

- @@ -3213,8 +3217,7 @@ static int inner_child(

-           * wait until the parent is ready with the

-           * setup, too... */

-          if (!barrier_place_and_sync(barrier)) /* #5 */

- -                return log_error_errno(SYNTHETIC_ERRNO(ESRCH),

- -                                       "Parent died too early");

- +                return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Parent died too early");

-  

-          if (arg_chdir)

-                  if (chdir(arg_chdir) < 0)

- @@ -3226,6 +3229,13 @@ static int inner_child(

-                          return r;

-          }

-  

- +        if (arg_console_mode != CONSOLE_PIPE) {

- +                /* So far our pty wasn't controlled by any process. Finally, it's time to change that, if we

- +                 * are configured for that. Acquire it as controlling tty. */

- +                if (ioctl(STDIN_FILENO, TIOCSCTTY) < 0)

- +                        return log_error_errno(errno, "Failed to acquire controlling TTY: %m");

- +        }

- +

-          log_debug("Inner child completed, invoking payload.");

-  

-          /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first

- -- 

- 2.26.2

- 

- 

- From 196b94c2db3f0b763480e98df98f288bcd044a6e Mon Sep 17 00:00:00 2001

- From: Lennart Poettering <lennart@poettering.net>

- Date: Thu, 17 Sep 2020 16:26:14 +0200

- Subject: [PATCH 5/5] nspawn: add --console=autopipe mode

- 

- By default we'll run a container in --console=interactive and

- --console=read-only mode depending if we are invoked on a tty or not so

- that the container always gets a /dev/console allocated, i.e is always

- suitable to run a full init system /as those typically expect a

- /dev/console to exist).

- 

- With the new --console=autopipe mode we do something similar, but

- slightly different: when not invoked on a tty we'll use --console=pipe.

- This means, if you invoke some tool in a container with this you'll get

- full inetractivity if you invoke it on a tty but things will also be

- very nicely pipeable. OTOH you cannot invoke a full init system like

- this, because you might or might not become a /dev/console this way...

- 

- Prompted-by: #17070

- 

- (I named this "autopipe" rather than "auto" or so, since the default

- mode probably should be named "auto" one day if we add a name for it,

- and this is so similar to "auto" except that it uses pipes in the

- non-tty case).

- ---

-  man/systemd-nspawn.xml | 21 ++++++++++++---------

-  src/nspawn/nspawn.c    | 12 +++++++++---

-  2 files changed, 21 insertions(+), 12 deletions(-)

- 

- diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml

- index 69558ac85c..b2c2a5006c 100644

- --- a/man/systemd-nspawn.xml

- +++ b/man/systemd-nspawn.xml

- @@ -1370,15 +1370,18 @@

-  

-          <listitem><para>Configures how to set up standard input, output and error output for the container

-          payload, as well as the <filename>/dev/console</filename> device for the container. Takes one of

- -        <option>interactive</option>, <option>read-only</option>, <option>passive</option>, or

- -        <option>pipe</option>. If <option>interactive</option>, a pseudo-TTY is allocated and made available

- -        as <filename>/dev/console</filename> in the container. It is then bi-directionally connected to the

- -        standard input and output passed to <command>systemd-nspawn</command>. <option>read-only</option> is

- -        similar but only the output of the container is propagated and no input from the caller is read. If

- -        <option>passive</option>, a pseudo TTY is allocated, but it is not connected anywhere. Finally, in

- -        <option>pipe</option> mode no pseudo TTY is allocated, but the standard input, output and error

- -        output file descriptors passed to <command>systemd-nspawn</command> are passed on — as they are — to

- -        the container payload, see the following paragraph. Defaults to <option>interactive</option> if

- +        <option>interactive</option>, <option>read-only</option>, <option>passive</option>,

- +        <option>pipe</option> or <option>autopipe</option>. If <option>interactive</option>, a pseudo-TTY is

- +        allocated and made available as <filename>/dev/console</filename> in the container. It is then

- +        bi-directionally connected to the standard input and output passed to

- +        <command>systemd-nspawn</command>. <option>read-only</option> is similar but only the output of the

- +        container is propagated and no input from the caller is read. If <option>passive</option>, a pseudo

- +        TTY is allocated, but it is not connected anywhere. In <option>pipe</option> mode no pseudo TTY is

- +        allocated, but the standard input, output and error output file descriptors passed to

- +        <command>systemd-nspawn</command> are passed on — as they are — to the container payload, see the

- +        following paragraph. Finally, <option>autopipe</option> mode operates like

- +        <option>interactive</option> when <command>systemd-nspawn</command> is invoked on a terminal, and

- +        like <option>pipe</option> otherwise. Defaults to <option>interactive</option> if

-          <command>systemd-nspawn</command> is invoked from a terminal, and <option>read-only</option>

-          otherwise.</para>

-  

- diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c

- index 783147f122..8837371232 100644

- --- a/src/nspawn/nspawn.c

- +++ b/src/nspawn/nspawn.c

- @@ -261,10 +261,11 @@ STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);

-  

-  static int handle_arg_console(const char *arg) {

-          if (streq(arg, "help")) {

- -                puts("interactive\n"

- -                     "read-only\n"

- +                puts("autopipe\n"

- +                     "interactive\n"

-                       "passive\n"

- -                     "pipe");

- +                     "pipe\n"

- +                     "read-only");

-                  return 0;

-          }

-  

- @@ -282,6 +283,11 @@ static int handle_arg_console(const char *arg) {

-                                   "Proceeding anyway.");

-  

-                  arg_console_mode = CONSOLE_PIPE;

- +        } else if (streq(arg, "autopipe")) {

- +                if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0)

- +                        arg_console_mode = CONSOLE_INTERACTIVE;

- +                else

- +                        arg_console_mode = CONSOLE_PIPE;

-          } else

-                  return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);

-  

- -- 

- 2.26.2

- 

@@ -0,0 +1,90 @@ 

+ From 0762f129c6a9c7bbdb5d575c486d5cf4f7fdae8d Mon Sep 17 00:00:00 2001

+ From: Richard Purdie <richard.purdie@linuxfoundation.org>

+ Date: Tue, 16 Feb 2021 12:17:36 +0000

+ Subject: [PATCH] proc: dont trigger mount error with invalid options on old

+  kernels

+ 

+ As of commit 4e39995371738b04d98d27b0d34ea8fe09ec9fab ("core: introduce

+ ProtectProc= and ProcSubset= to expose hidepid= and subset= procfs

+ mount options") kernels older than v5.8 generate multple warnings at

+ boot, as seen in this Yocto build from today:

+ 

+      qemux86-64 login: root

+      [   65.829009] proc: Bad value for 'hidepid'

+      root@qemux86-64:~# dmesg|grep proc:

+      [   16.990706] proc: Bad value for 'hidepid'

+      [   28.060178] proc: Bad value for 'hidepid'

+      [   28.874229] proc: Bad value for 'hidepid'

+      [   32.685107] proc: Bad value for 'hidepid'

+      [   65.829009] proc: Bad value for 'hidepid'

+      root@qemux86-64:~#

+ 

+ We see reports of the issue as in general its hard to someone to tell

+ the difference between an error in dmesg which they should worry about and

+ one that is harmless. This adds support burden to developers so Yocto

+ Project has added this patch.

+ 

+ The commit that triggers this is systemd v247-rc1~378^2~3 -- so any

+ systemd 247 and above plus kernel v5.7 or older will need this.

+ 

+ As noted in https://github.com/systemd/systemd/issues/16896

+ it is possible changes could be backported to different kernel versions

+ so the test isn't 100% foolproof but does give better results than a

+ continual stream of bug reports.

+ 

+ Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>

+ 

+ Changes from Anita Zhang <the.anitazha@gmail.com>

+ - Use 5.6.13-0_fbk9 version comparison for FB build

+ ---

+  src/core/namespace.c | 22 ++++++++++++++++++++--

+  1 file changed, 20 insertions(+), 2 deletions(-)

+ 

+ diff --git a/src/core/namespace.c b/src/core/namespace.c

+ index d47531408b..8be8352a8e 100644

+ --- a/src/core/namespace.c

+ +++ b/src/core/namespace.c

+ @@ -4,7 +4,9 @@

+  #include <linux/loop.h>

+  #include <sched.h>

+  #include <stdio.h>

+ +#include <stdlib.h>

+  #include <sys/mount.h>

+ +#include <sys/utsname.h>

+  #include <unistd.h>

+  #include <linux/fs.h>

+  

+ @@ -1018,12 +1020,28 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {

+          _cleanup_free_ char *opts = NULL;

+          const char *entry_path;

+          int r, n;

+ +        struct utsname uts;

+ +        bool old = false;

+  

+          assert(m);

+          assert(ns_info);

+  

+ -        if (ns_info->protect_proc != PROTECT_PROC_DEFAULT ||

+ -            ns_info->proc_subset != PROC_SUBSET_ALL) {

+ +        /* If uname says that the system is older than v5.6.13-0_fbk9, then the textual hidepid= stuff is not

+ +         * supported by the kernel, and thus the per-instance hidepid= neither, which means we

+ +         * really don't want to use it, since it would affect our host's /proc * mount. Hence let's

+ +         * gracefully fallback to a classic, unrestricted version. */

+ +

+ +        r = uname(&uts);

+ +        if (r < 0)

+ +               return -errno;

+ +

+ +        if (strverscmp(uts.release, "5.6.13-0_fbk9") < 0) {

+ +                log_debug("Pre v5.6.13-0_fbk9 kernel detected [v%s] - skipping hidepid=", uts.release);

+ +                old = true;

+ +        }

+ +

+ +        if (!old && (ns_info->protect_proc != PROTECT_PROC_DEFAULT ||

+ +            ns_info->proc_subset != PROC_SUBSET_ALL)) {

+  

+                  /* Starting with kernel 5.8 procfs' hidepid= logic is truly per-instance (previously it

+                   * pretended to be per-instance but actually was per-namespace), hence let's make use of it

+ -- 

+ 2.30.2

+ 

file added
+84
@@ -0,0 +1,84 @@ 

+ From c225bc59b8907de11f389bd8efb82155ccde75a7 Mon Sep 17 00:00:00 2001

+ From: Richard Purdie <richard.purdie@linuxfoundation.org>

+ Date: Tue, 16 Feb 2021 12:17:36 +0000

+ Subject: [PATCH] proc: dont trigger mount error with invalid options on old

+  kernels

+ 

+ As of commit 4e39995371738b04d98d27b0d34ea8fe09ec9fab ("core: introduce

+ ProtectProc= and ProcSubset= to expose hidepid= and subset= procfs

+ mount options") kernels older than v5.8 generate multple warnings at

+ boot, as seen in this Yocto build from today:

+ 

+      qemux86-64 login: root

+      [   65.829009] proc: Bad value for 'hidepid'

+      root@qemux86-64:~# dmesg|grep proc:

+      [   16.990706] proc: Bad value for 'hidepid'

+      [   28.060178] proc: Bad value for 'hidepid'

+      [   28.874229] proc: Bad value for 'hidepid'

+      [   32.685107] proc: Bad value for 'hidepid'

+      [   65.829009] proc: Bad value for 'hidepid'

+      root@qemux86-64:~#

+ 

+ We see reports of the issue as in general its hard to someone to tell

+ the difference between an error in dmesg which they should worry about and

+ one that is harmless. This adds support burden to developers so Yocto

+ Project has added this patch.

+ 

+ The commit that triggers this is systemd v247-rc1~378^2~3 -- so any

+ systemd 247 and above plus kernel v5.7 or older will need this.

+ 

+ As noted in https://github.com/systemd/systemd/issues/16896

+ it is possible changes could be backported to different kernel versions

+ so the test isn't 100% foolproof but does give better results than a

+ continual stream of bug reports.

+ 

+ Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>

+ ---

+  src/core/namespace.c | 22 ++++++++++++++++++++--

+  1 file changed, 20 insertions(+), 2 deletions(-)

+ 

+ diff --git a/src/core/namespace.c b/src/core/namespace.c

+ index 4ed0991b56d1..3fa2d4e9d640 100644

+ --- a/src/core/namespace.c

+ +++ b/src/core/namespace.c

+ @@ -4,7 +4,9 @@

+  #include <linux/loop.h>

+  #include <sched.h>

+  #include <stdio.h>

+ +#include <stdlib.h>

+  #include <sys/mount.h>

+ +#include <sys/utsname.h>

+  #include <unistd.h>

+  #include <linux/fs.h>

+  

+ @@ -881,12 +883,28 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {

+          _cleanup_free_ char *opts = NULL;

+          const char *entry_path;

+          int r, n;

+ +        struct utsname uts;

+ +        bool old = false;

+  

+          assert(m);

+          assert(ns_info);

+  

+ -        if (ns_info->protect_proc != PROTECT_PROC_DEFAULT ||

+ -            ns_info->proc_subset != PROC_SUBSET_ALL) {

+ +        /* If uname says that the system is older than v5.8, then the textual hidepid= stuff is not

+ +         * supported by the kernel, and thus the per-instance hidepid= neither, which means we

+ +         * really don't want to use it, since it would affect our host's /proc * mount. Hence let's

+ +         * gracefully fallback to a classic, unrestricted version. */

+ +

+ +        r = uname(&uts);

+ +        if (r < 0)

+ +               return -errno;

+ +

+ +        if (strverscmp(uts.release, "5.8") < 0) {

+ +                log_debug("Pre v5.8 kernel detected [v%s] - skipping hidepid=", uts.release);

+ +                old = true;

+ +        }

+ +

+ +        if (!old && (ns_info->protect_proc != PROTECT_PROC_DEFAULT ||

+ +            ns_info->proc_subset != PROC_SUBSET_ALL)) {

+  

+                  /* Starting with kernel 5.8 procfs' hidepid= logic is truly per-instance (previously it

+                   * pretended to be per-instance but actually was per-namespace), hence let's make use of it

file added
+86
@@ -0,0 +1,86 @@ 

+ From 0db68800c756f298ef45584ac01915c2cb2ce359 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Mon, 16 Aug 2021 23:47:40 +0900

+ Subject: [PATCH 1/2] ethtool: make the size of 'features' array static

+ 

+ ---

+  src/shared/ethtool-util.c | 2 +-

+  src/shared/ethtool-util.h | 2 +-

+  2 files changed, 2 insertions(+), 2 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index f77f6943ca4f..699c7a97ab97 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -501,7 +501,7 @@ static int set_features_bit(

+          return found ? 0 : -ENODATA;

+  }

+  

+ -int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features) {

+ +int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]) {

+          _cleanup_free_ struct ethtool_gstrings *strings = NULL;

+          struct ethtool_sfeatures *sfeatures;

+          struct ifreq ifr = {};

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index 7d287666249a..f0fc40b0595f 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -88,7 +88,7 @@ int ethtool_get_link_info(int *ethtool_fd, const char *ifname,

+  int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct ether_addr *ret);

+  int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts);

+  int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring);

+ -int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features);

+ +int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]);

+  int ethtool_set_glinksettings(int *ethtool_fd, const char *ifname,

+                                int autonegotiation, const uint32_t advertise[static N_ADVERTISE],

+                                uint64_t speed, Duplex duplex, NetDevPort port);

+ 

+ From c2f2250e5c52ec3745a462e3f55a94c133786df8 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Tue, 17 Aug 2021 00:44:00 +0900

+ Subject: [PATCH 2/2] ethtool: make ethtool_set_features() return earlier when

+  nothing is requested

+ 

+ ---

+  src/shared/ethtool-util.c | 16 +++++++++++++---

+  1 file changed, 13 insertions(+), 3 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index 699c7a97ab97..4ca90615f3c1 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -505,12 +505,22 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+          _cleanup_free_ struct ethtool_gstrings *strings = NULL;

+          struct ethtool_sfeatures *sfeatures;

+          struct ifreq ifr = {};

+ -        int i, r;

+ +        bool have = false;

+ +        int r;

+  

+          assert(ethtool_fd);

+          assert(ifname);

+          assert(features);

+  

+ +        for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++)

+ +                if (features[i] >= 0) {

+ +                        have = true;

+ +                        break;

+ +                }

+ +

+ +        if (!have)

+ +                return 0;

+ +

+          r = ethtool_connect(ethtool_fd);

+          if (r < 0)

+                  return r;

+ @@ -525,8 +535,8 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+          sfeatures->cmd = ETHTOOL_SFEATURES;

+          sfeatures->size = DIV_ROUND_UP(strings->len, 32U);

+  

+ -        for (i = 0; i < _NET_DEV_FEAT_MAX; i++)

+ -                if (features[i] != -1) {

+ +        for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++)

+ +                if (features[i] >= 0) {

+                          r = set_features_bit(strings, netdev_feature_table[i], features[i], sfeatures);

+                          if (r < 0) {

+                                  log_debug_errno(r, "ethtool: could not find feature, ignoring: %s", netdev_feature_table[i]);

file added
+143
@@ -0,0 +1,143 @@ 

+ From e9f92c88163841d3f1d29fa5b44ae4c6f71bb014 Mon Sep 17 00:00:00 2001

+ From: Daan De Meyer <daan.j.demeyer@gmail.com>

+ Date: Wed, 18 Aug 2021 07:59:13 +0100

+ Subject: [PATCH] udev: Support "max" string for BufferSize options (#20458)

+ 

+ "max" indicates the hardware advertised maximum queue buffer size

+ should be used.

+ 

+ The max sizes can be checked by running `ethtool -g <dev>` (Preset maximums).

+ Since the buffer sizes can't be set to 0 by users, internally we use 0 to

+ indicate that the hardware advertised maximum should be used.

+ ---

+  man/systemd.link.xml      | 20 ++++++++++++--------

+  src/shared/ethtool-util.c | 40 +++++++++++++++++++++++++--------------

+  src/shared/ethtool-util.h |  2 ++

+  3 files changed, 40 insertions(+), 22 deletions(-)

+ 

+ diff --git a/man/systemd.link.xml b/man/systemd.link.xml

+ index 1c18f35fc8..fd744ebaed 100644

+ --- a/man/systemd.link.xml

+ +++ b/man/systemd.link.xml

+ @@ -735,29 +735,33 @@

+        <varlistentry>

+          <term><varname>RxBufferSize=</varname></term>

+          <listitem>

+ -          <para>Takes an integer. Specifies the maximum number of pending packets in the NIC receive buffer.

+ -          When unset, the kernel's default will be used.</para>

+ +          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ +          in the NIC receive buffer. When unset, the kernel's default will be used. If set to

+ +          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+          <term><varname>RxMiniBufferSize=</varname></term>

+          <listitem>

+ -          <para>Takes an integer. Specifies the maximum number of pending packets in the NIC mini receive buffer.

+ -          When unset, the kernel's default will be used.</para>

+ +          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ +          in the NIC mini receive buffer. When unset, the kernel's default will be used. If set to

+ +          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+          <term><varname>RxJumboBufferSize=</varname></term>

+          <listitem>

+ -          <para>Takes an integer. Specifies the maximum number of pending packets in the NIC jumbo receive buffer.

+ -          When unset, the kernel's default will be used.</para>

+ +          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ +          in the NIC jumbo receive buffer. When unset, the kernel's default will be used. If set to

+ +          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+          <term><varname>TxBufferSize=</varname></term>

+          <listitem>

+ -          <para>Takes an integer. Specifies the maximum number of pending packets in the NIC transmit buffer.

+ -          When unset, the kernel's default will be used.</para>

+ +          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ +          in the NIC transmit buffer. When unset, the kernel's default will be used. If set to

+ +          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index f77f6943ca..ed251ec8dd 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -399,16 +399,24 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+                  return -errno;

+  

+          if (ring->rx_pending_set)

+ -                UPDATE(ecmd.rx_pending, ring->rx_pending, need_update);

+ +                UPDATE(ecmd.rx_pending,

+ +                       ring->rx_pending == 0 ? ecmd.rx_max_pending : ring->rx_pending,

+ +                       need_update);

+  

+          if (ring->rx_mini_pending_set)

+ -                UPDATE(ecmd.rx_mini_pending, ring->rx_mini_pending, need_update);

+ +                UPDATE(ecmd.rx_mini_pending,

+ +                       ring->rx_mini_pending == 0 ? ecmd.rx_mini_max_pending : ring->rx_mini_pending,

+ +                       need_update);

+  

+          if (ring->rx_jumbo_pending_set)

+ -                UPDATE(ecmd.rx_jumbo_pending, ring->rx_jumbo_pending, need_update);

+ +                UPDATE(ecmd.rx_jumbo_pending,

+ +                       ring->rx_jumbo_pending == 0 ? ecmd.rx_jumbo_max_pending : ring->rx_jumbo_pending,

+ +                       need_update);

+  

+          if (ring->tx_pending_set)

+ -                UPDATE(ecmd.tx_pending, ring->tx_pending, need_update);

+ +                UPDATE(ecmd.tx_pending,

+ +                       ring->tx_pending == 0 ? ecmd.tx_max_pending : ring->tx_pending,

+ +                       need_update);

+  

+          if (!need_update)

+                  return 0;

+ @@ -1037,16 +1045,20 @@ int config_parse_nic_buffer_size(

+          assert(rvalue);

+          assert(data);

+  

+ -        r = safe_atou32(rvalue, &k);

+ -        if (r < 0) {

+ -                log_syntax(unit, LOG_WARNING, filename, line, r,

+ -                           "Failed to parse interface buffer value, ignoring: %s", rvalue);

+ -                return 0;

+ -        }

+ -        if (k < 1) {

+ -                log_syntax(unit, LOG_WARNING, filename, line, 0,

+ -                           "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ -                return 0;

+ +        if (streq(rvalue, "max"))

+ +                k = 0;

+ +        else {

+ +                r = safe_atou32(rvalue, &k);

+ +                if (r < 0) {

+ +                        log_syntax(unit, LOG_WARNING, filename, line, r,

+ +                                "Failed to parse interface buffer value, ignoring: %s", rvalue);

+ +                        return 0;

+ +                }

+ +                if (k < 1) {

+ +                        log_syntax(unit, LOG_WARNING, filename, line, 0,

+ +                                "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ +                        return 0;

+ +                }

+          }

+  

+          if (streq(lvalue, "RxBufferSize")) {

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index 7d28766624..aea131914e 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -70,6 +70,8 @@ typedef struct netdev_channels {

+  } netdev_channels;

+  

+  typedef struct netdev_ring_param {

+ +        /* For any of the 4 following settings, a value of 0 indicates the hardware advertised maximum should

+ +         * be used. */

+          uint32_t rx_pending;

+          uint32_t rx_mini_pending;

+          uint32_t rx_jumbo_pending;

+ -- 

+ 2.31.1

+ 

file added
+425
@@ -0,0 +1,425 @@ 

+ From 78e57b79c8790448412acca41e5d4495366305a6 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Wed, 18 Aug 2021 16:41:11 +0900

+ Subject: [PATCH] udev: make RxChannels= or friends also accept "max"

+ 

+ Follow-up for 406041b7de767316674eb6a2f98ad466577ce8a4.

+ 

+ Also, this makes

+ - the settings accept an empty string,

+ - if the specified value is too large, also use the advertised maximum

+   value.

+ - mention the range of the value in the man page.

+ ---

+  man/systemd.link.xml                 |  49 ++------

+  src/shared/ethtool-util.c            | 170 ++++++++++-----------------

+  src/shared/ethtool-util.h            |  36 +++---

+  src/udev/net/link-config-gperf.gperf |  16 +--

+  4 files changed, 90 insertions(+), 181 deletions(-)

+ 

+ diff --git a/man/systemd.link.xml b/man/systemd.link.xml

+ index fd744ebaed..dfb02073b2 100644

+ --- a/man/systemd.link.xml

+ +++ b/man/systemd.link.xml

+ @@ -710,58 +710,27 @@

+        </varlistentry>

+        <varlistentry>

+          <term><varname>RxChannels=</varname></term>

+ -        <listitem>

+ -          <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>TxChannels=</varname></term>

+ -        <listitem>

+ -          <para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>OtherChannels=</varname></term>

+ -        <listitem>

+ -          <para>Sets the number of other channels (a number between 1 and 4294967295).</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>CombinedChannels=</varname></term>

+          <listitem>

+ -          <para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>

+ +          <para>Specifies the number of receive, transmit, other, or combined channels, respectively.

+ +          Takes an unsigned integer in the range 1…4294967295 or <literal>max</literal>. If set to

+ +          <literal>max</literal>, the advertised maximum value of the hardware will be used. When

+ +          unset, the number will not be changed. Defaults to unset.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+          <term><varname>RxBufferSize=</varname></term>

+ -        <listitem>

+ -          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ -          in the NIC receive buffer. When unset, the kernel's default will be used. If set to

+ -          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>RxMiniBufferSize=</varname></term>

+ -        <listitem>

+ -          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ -          in the NIC mini receive buffer. When unset, the kernel's default will be used. If set to

+ -          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>RxJumboBufferSize=</varname></term>

+ -        <listitem>

+ -          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ -          in the NIC jumbo receive buffer. When unset, the kernel's default will be used. If set to

+ -          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+ -        </listitem>

+ -      </varlistentry>

+ -      <varlistentry>

+          <term><varname>TxBufferSize=</varname></term>

+          <listitem>

+ -          <para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets

+ -          in the NIC transmit buffer. When unset, the kernel's default will be used. If set to

+ -          <literal>max</literal>, the hardware's advertised maximum size will be used.</para>

+ +          <para>Specifies the maximum number of pending packets in the NIC receive buffer, mini receive

+ +          buffer, jumbo receive buffer, or transmit buffer, respectively. Takes an unsigned integer in

+ +          the range 1…4294967295 or <literal>max</literal>. If set to <literal>max</literal>, the

+ +          advertised maximum value of the hardware will be used. When unset, the number will not be

+ +          changed. Defaults to unset.</para>

+          </listitem>

+        </varlistentry>

+        <varlistentry>

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index ed251ec8dd..2d41d861ba 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -329,6 +329,17 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et

+                  dest = _v;                             \

+          } while(false)

+  

+ +#define UPDATE_WITH_MAX(dest, max, val, updated)       \

+ +        do {                                           \

+ +                typeof(dest) _v = (val);               \

+ +                typeof(dest) _max = (max);             \

+ +                if (_v == 0 || _v > _max)              \

+ +                        _v = _max;                     \

+ +                if (dest != _v)                        \

+ +                        updated = true;                \

+ +                dest = _v;                             \

+ +        } while(false)

+ +

+  int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {

+          struct ethtool_wolinfo ecmd = {

+                  .cmd = ETHTOOL_GWOL,

+ @@ -382,10 +393,10 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+          assert(ifname);

+          assert(ring);

+  

+ -        if (!ring->rx_pending_set &&

+ -            !ring->rx_mini_pending_set &&

+ -            !ring->rx_jumbo_pending_set &&

+ -            !ring->tx_pending_set)

+ +        if (!ring->rx.set &&

+ +            !ring->rx_mini.set &&

+ +            !ring->rx_jumbo.set &&

+ +            !ring->tx.set)

+                  return 0;

+  

+          r = ethtool_connect(ethtool_fd);

+ @@ -398,25 +409,17 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+          if (r < 0)

+                  return -errno;

+  

+ -        if (ring->rx_pending_set)

+ -                UPDATE(ecmd.rx_pending,

+ -                       ring->rx_pending == 0 ? ecmd.rx_max_pending : ring->rx_pending,

+ -                       need_update);

+ +        if (ring->rx.set)

+ +                UPDATE_WITH_MAX(ecmd.rx_pending, ecmd.rx_max_pending, ring->rx.value, need_update);

+  

+ -        if (ring->rx_mini_pending_set)

+ -                UPDATE(ecmd.rx_mini_pending,

+ -                       ring->rx_mini_pending == 0 ? ecmd.rx_mini_max_pending : ring->rx_mini_pending,

+ -                       need_update);

+ +        if (ring->rx_mini.set)

+ +                UPDATE_WITH_MAX(ecmd.rx_mini_pending, ecmd.rx_mini_max_pending, ring->rx_mini.value, need_update);

+  

+ -        if (ring->rx_jumbo_pending_set)

+ -                UPDATE(ecmd.rx_jumbo_pending,

+ -                       ring->rx_jumbo_pending == 0 ? ecmd.rx_jumbo_max_pending : ring->rx_jumbo_pending,

+ -                       need_update);

+ +        if (ring->rx_jumbo.set)

+ +                UPDATE_WITH_MAX(ecmd.rx_jumbo_pending, ecmd.rx_jumbo_max_pending, ring->rx_jumbo.value, need_update);

+  

+ -        if (ring->tx_pending_set)

+ -                UPDATE(ecmd.tx_pending,

+ -                       ring->tx_pending == 0 ? ecmd.tx_max_pending : ring->tx_pending,

+ -                       need_update);

+ +        if (ring->tx.set)

+ +                UPDATE_WITH_MAX(ecmd.tx_pending, ecmd.tx_max_pending, ring->tx.value, need_update);

+  

+          if (!need_update)

+                  return 0;

+ @@ -832,10 +835,10 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha

+          assert(ifname);

+          assert(channels);

+  

+ -        if (!channels->rx_count_set &&

+ -            !channels->tx_count_set &&

+ -            !channels->other_count_set &&

+ -            !channels->combined_count_set)

+ +        if (!channels->rx.set &&

+ +            !channels->tx.set &&

+ +            !channels->other.set &&

+ +            !channels->combined.set)

+                  return 0;

+  

+          r = ethtool_connect(fd);

+ @@ -848,17 +851,17 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha

+          if (r < 0)

+                  return -errno;

+  

+ -        if (channels->rx_count_set)

+ -                UPDATE(ecmd.rx_count, channels->rx_count, need_update);

+ +        if (channels->rx.set)

+ +                UPDATE_WITH_MAX(ecmd.rx_count, ecmd.max_rx, channels->rx.value, need_update);

+  

+ -        if (channels->tx_count_set)

+ -                UPDATE(ecmd.tx_count, channels->tx_count, need_update);

+ +        if (channels->tx.set)

+ +                UPDATE_WITH_MAX(ecmd.tx_count, ecmd.max_tx, channels->tx.value, need_update);

+  

+ -        if (channels->other_count_set)

+ -                UPDATE(ecmd.other_count, channels->other_count, need_update);

+ +        if (channels->other.set)

+ +                UPDATE_WITH_MAX(ecmd.other_count, ecmd.max_other, channels->other.value, need_update);

+  

+ -        if (channels->combined_count_set)

+ -                UPDATE(ecmd.combined_count, channels->combined_count, need_update);

+ +        if (channels->combined.set)

+ +                UPDATE_WITH_MAX(ecmd.combined_count, ecmd.max_combined, channels->combined.value, need_update);

+  

+          if (!need_update)

+                  return 0;

+ @@ -917,57 +920,6 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au

+          return 0;

+  }

+  

+ -int config_parse_channel(

+ -                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) {

+ -

+ -        netdev_channels *channels = data;

+ -        uint32_t k;

+ -        int r;

+ -

+ -        assert(filename);

+ -        assert(section);

+ -        assert(lvalue);

+ -        assert(rvalue);

+ -        assert(data);

+ -

+ -        r = safe_atou32(rvalue, &k);

+ -        if (r < 0) {

+ -                log_syntax(unit, LOG_WARNING, filename, line, r,

+ -                           "Failed to parse channel value for %s=, ignoring: %s", lvalue, rvalue);

+ -                return 0;

+ -        }

+ -        if (k < 1) {

+ -                log_syntax(unit, LOG_WARNING, filename, line, 0,

+ -                           "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ -                return 0;

+ -        }

+ -

+ -        if (streq(lvalue, "RxChannels")) {

+ -                channels->rx_count = k;

+ -                channels->rx_count_set = true;

+ -        } else if (streq(lvalue, "TxChannels")) {

+ -                channels->tx_count = k;

+ -                channels->tx_count_set = true;

+ -        } else if (streq(lvalue, "OtherChannels")) {

+ -                channels->other_count = k;

+ -                channels->other_count_set = true;

+ -        } else if (streq(lvalue, "CombinedChannels")) {

+ -                channels->combined_count = k;

+ -                channels->combined_count_set = true;

+ -        }

+ -

+ -        return 0;

+ -}

+ -

+  int config_parse_advertise(

+                  const char *unit,

+                  const char *filename,

+ @@ -1023,7 +975,7 @@ int config_parse_advertise(

+          }

+  }

+  

+ -int config_parse_nic_buffer_size(

+ +int config_parse_ring_buffer_or_channel(

+                  const char *unit,

+                  const char *filename,

+                  unsigned line,

+ @@ -1035,7 +987,7 @@ int config_parse_nic_buffer_size(

+                  void *data,

+                  void *userdata) {

+  

+ -        netdev_ring_param *ring = data;

+ +        u32_opt *dst = data;

+          uint32_t k;

+          int r;

+  

+ @@ -1045,36 +997,32 @@ int config_parse_nic_buffer_size(

+          assert(rvalue);

+          assert(data);

+  

+ -        if (streq(rvalue, "max"))

+ -                k = 0;

+ -        else {

+ -                r = safe_atou32(rvalue, &k);

+ -                if (r < 0) {

+ -                        log_syntax(unit, LOG_WARNING, filename, line, r,

+ -                                "Failed to parse interface buffer value, ignoring: %s", rvalue);

+ -                        return 0;

+ -                }

+ -                if (k < 1) {

+ -                        log_syntax(unit, LOG_WARNING, filename, line, 0,

+ -                                "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ -                        return 0;

+ -                }

+ +        if (isempty(rvalue)) {

+ +                dst->value = 0;

+ +                dst->set = false;

+ +                return 0;

+ +        }

+ +

+ +        if (streq(rvalue, "max")) {

+ +                dst->value = 0;

+ +                dst->set = true;

+ +                return 0;

+          }

+  

+ -        if (streq(lvalue, "RxBufferSize")) {

+ -                ring->rx_pending = k;

+ -                ring->rx_pending_set = true;

+ -        } else if (streq(lvalue, "RxMiniBufferSize")) {

+ -                ring->rx_mini_pending = k;

+ -                ring->rx_mini_pending_set = true;

+ -        } else if (streq(lvalue, "RxJumboBufferSize")) {

+ -                ring->rx_jumbo_pending = k;

+ -                ring->rx_jumbo_pending_set = true;

+ -        } else if (streq(lvalue, "TxBufferSize")) {

+ -                ring->tx_pending = k;

+ -                ring->tx_pending_set = true;

+ +        r = safe_atou32(rvalue, &k);

+ +        if (r < 0) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, r,

+ +                           "Failed to parse %s=, ignoring: %s", lvalue, rvalue);

+ +                return 0;

+ +        }

+ +        if (k < 1) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, 0,

+ +                           "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ +                return 0;

+          }

+  

+ +        dst->value = k;

+ +        dst->set = true;

+          return 0;

+  }

+  

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index aea131914e..8fdbdec39a 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -57,30 +57,23 @@ struct ethtool_link_usettings {

+          } link_modes;

+  };

+  

+ +typedef struct u32_opt {

+ +        uint32_t value; /* a value of 0 indicates the hardware advertised maximum should be used.*/

+ +        bool set;

+ +} u32_opt;

+ +

+  typedef struct netdev_channels {

+ -        uint32_t rx_count;

+ -        uint32_t tx_count;

+ -        uint32_t other_count;

+ -        uint32_t combined_count;

+ -

+ -        bool rx_count_set;

+ -        bool tx_count_set;

+ -        bool other_count_set;

+ -        bool combined_count_set;

+ +        u32_opt rx;

+ +        u32_opt tx;

+ +        u32_opt other;

+ +        u32_opt combined;

+  } netdev_channels;

+  

+  typedef struct netdev_ring_param {

+ -        /* For any of the 4 following settings, a value of 0 indicates the hardware advertised maximum should

+ -         * be used. */

+ -        uint32_t rx_pending;

+ -        uint32_t rx_mini_pending;

+ -        uint32_t rx_jumbo_pending;

+ -        uint32_t tx_pending;

+ -

+ -        bool rx_pending_set;

+ -        bool rx_mini_pending_set;

+ -        bool rx_jumbo_pending_set;

+ -        bool tx_pending_set;

+ +        u32_opt rx;

+ +        u32_opt rx_mini;

+ +        u32_opt rx_jumbo;

+ +        u32_opt tx;

+  } netdev_ring_param;

+  

+  int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret);

+ @@ -111,6 +104,5 @@ enum ethtool_link_mode_bit_indices ethtool_link_mode_bit_from_string(const char

+  CONFIG_PARSER_PROTOTYPE(config_parse_duplex);

+  CONFIG_PARSER_PROTOTYPE(config_parse_wol);

+  CONFIG_PARSER_PROTOTYPE(config_parse_port);

+ -CONFIG_PARSER_PROTOTYPE(config_parse_channel);

+  CONFIG_PARSER_PROTOTYPE(config_parse_advertise);

+ -CONFIG_PARSER_PROTOTYPE(config_parse_nic_buffer_size);

+ +CONFIG_PARSER_PROTOTYPE(config_parse_ring_buffer_or_channel);

+ diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf

+ index e2f07d758b..d0190da5cb 100644

+ --- a/src/udev/net/link-config-gperf.gperf

+ +++ b/src/udev/net/link-config-gperf.gperf

+ @@ -58,15 +58,15 @@ Link.TCP6SegmentationOffload,          config_parse_tristate,                 0,

+  Link.UDPSegmentationOffload,           config_parse_warn_compat,              DISABLED_LEGACY,               0

+  Link.GenericReceiveOffload,            config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+  Link.LargeReceiveOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ -Link.RxChannels,                       config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

+ -Link.TxChannels,                       config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

+ -Link.OtherChannels,                    config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

+ -Link.CombinedChannels,                 config_parse_channel,                  0,                             offsetof(LinkConfig, channels)

+ +Link.RxChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ +Link.TxChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ +Link.OtherChannels,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ +Link.CombinedChannels,                 config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+  Link.Advertise,                        config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ -Link.RxBufferSize,                     config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

+ -Link.RxMiniBufferSize,                 config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

+ -Link.RxJumboBufferSize,                config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

+ -Link.TxBufferSize,                     config_parse_nic_buffer_size,          0,                             offsetof(LinkConfig, ring)

+ +Link.RxBufferSize,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ +Link.RxMiniBufferSize,                 config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ +Link.RxJumboBufferSize,                config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ +Link.TxBufferSize,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+  Link.RxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+  Link.TxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+  Link.AutoNegotiationFlowControl,       config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ -- 

+ 2.31.1

+ 

file added
+561
@@ -0,0 +1,561 @@ 

+ From a1661a140c97a9e8fd90ee00f2de6baa214c9076 Mon Sep 17 00:00:00 2001

+ From: Daan De Meyer <daan.j.demeyer@gmail.com>

+ Date: Wed, 18 Aug 2021 13:52:00 +0100

+ Subject: [PATCH] udev: Add support for configuring nic coalescing settings

+ 

+ These are configured via the corresponding ethtool ioctl.

+ ---

+  man/systemd.link.xml                       |  71 +++++++

+  src/shared/ethtool-util.c                  | 205 +++++++++++++++++++++

+  src/shared/ethtool-util.h                  |  29 +++

+  src/udev/net/link-config-gperf.gperf       | 124 ++++++++-----

+  src/udev/net/link-config.c                 |   4 +

+  src/udev/net/link-config.h                 |   1 +

+  test/fuzz/fuzz-link-parser/directives.link |  22 +++

+  7 files changed, 405 insertions(+), 51 deletions(-)

+ 

+ diff --git a/man/systemd.link.xml b/man/systemd.link.xml

+ index dfb02073b2..6d8dcb9af7 100644

+ --- a/man/systemd.link.xml

+ +++ b/man/systemd.link.xml

+ @@ -773,6 +773,77 @@

+            accept. An unsigned integer in the range 1…65535. Defaults to unset.</para>

+          </listitem>

+        </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>UseAdaptiveRxCoalesce=</varname></term>

+ +        <term><varname>UseAdaptiveTxCoalesce=</varname></term>

+ +        <listitem>

+ +          <para>Boolean properties that, when set, enable/disable adaptive Rx/Tx coalescing if the hardware

+ +          supports it. When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>RxCoalesceSec=</varname></term>

+ +        <term><varname>RxCoalesceIrqSec=</varname></term>

+ +        <term><varname>RxCoalesceLowSec=</varname></term>

+ +        <term><varname>RxCoalesceHighSec=</varname></term>

+ +        <term><varname>TxCoalesceSec=</varname></term>

+ +        <term><varname>TxCoalesceIrqSec=</varname></term>

+ +        <term><varname>TxCoalesceLowSec=</varname></term>

+ +        <term><varname>TxCoalesceHighSec=</varname></term>

+ +        <listitem>

+ +          <para>These properties configure the delay before Rx/Tx interrupts are generated after a packet is

+ +          sent/received. The <literal>Irq</literal> properties come into effect when the host is servicing an

+ +          IRQ. The <literal>Low</literal> and <literal>High</literal> properties come into effect when the

+ +          packet rate drops below the low packet rate threshold or exceeds the high packet rate threshold

+ +          respectively if adaptive Rx/Tx coalescing is enabled. When unset, the kernel's defaults will be

+ +          used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +        <varlistentry>

+ +        <term><varname>RxMaxCoalescedFrames=</varname></term>

+ +        <term><varname>RxMaxCoalescedIrqFrames=</varname></term>

+ +        <term><varname>RxMaxCoalescedLowFrames=</varname></term>

+ +        <term><varname>RxMaxCoalescedHighFrames=</varname></term>

+ +        <term><varname>TxMaxCoalescedFrames=</varname></term>

+ +        <term><varname>TxMaxCoalescedIrqFrames=</varname></term>

+ +        <term><varname>TxMaxCoalescedLowFrames=</varname></term>

+ +        <term><varname>TxMaxCoalescedHighFrames=</varname></term>

+ +        <listitem>

+ +          <para>These properties configure the maximum number of frames that are sent/received before a Rx/Tx

+ +          interrupt is generated. The <literal>Irq</literal> properties come into effect when the host is

+ +          servicing an IRQ. The <literal>Low</literal> and <literal>High</literal> properties come into

+ +          effect when the packet rate drops below the low packet rate threshold or exceeds the high packet

+ +          rate threshold respectively if adaptive Rx/Tx coalescing is enabled. When unset, the kernel's

+ +          defaults will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>CoalescePacketRateLow=</varname></term>

+ +        <term><varname>CoalescePacketRateHigh=</varname></term>

+ +        <listitem>

+ +          <para>These properties configure the low and high packet rate (expressed in packets per second)

+ +          threshold respectively and are used to determine when the corresponding coalescing settings for low

+ +          and high packet rates come into effect if adaptive Rx/Tx coalescing is enabled. If unset, the

+ +          kernel's defaults will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>CoalescePacketRateSampleIntervalSec=</varname></term>

+ +        <listitem>

+ +          <para>Configures how often to sample the packet rate used for adaptive Rx/Tx coalescing. This

+ +          property cannot be zero. This lowest time granularity supported by this property is seconds.

+ +          Partial seconds will be rounded up before being passed to the kernel. If unset, the kernel's

+ +          default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>StatisticsBlockCoalesceSec=</varname></term>

+ +        <listitem>

+ +          <para>How long to delay driver in-memory statistics block updates. If the driver does not have an

+ +          in-memory statistic block, this property is ignored. This property cannot be zero. If unset, the

+ +          kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+  

+      </variablelist>

+    </refsect1>

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index 2d41d861ba..f7f553dd29 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -14,6 +14,7 @@

+  #include "memory-util.h"

+  #include "socket-util.h"

+  #include "string-table.h"

+ +#include "strv.h"

+  #include "strxcpyx.h"

+  

+  static const char* const duplex_table[_DUP_MAX] = {

+ @@ -1091,3 +1092,207 @@ int config_parse_wol(

+  

+          return 0;

+  }

+ +

+ +int config_parse_coalesce_u32(

+ +                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) {

+ +        u32_opt *dst = data;

+ +        uint32_t k;

+ +        int r;

+ +

+ +        if (isempty(rvalue)) {

+ +                dst->value = 0;

+ +                dst->set = false;

+ +                return 0;

+ +        }

+ +

+ +        r = safe_atou32(rvalue, &k);

+ +        if (r < 0) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, r,

+ +                           "Failed to parse %s=, ignoring: %s", lvalue, rvalue);

+ +                return 0;

+ +        }

+ +

+ +        dst->value = k;

+ +        dst->set = true;

+ +        return 0;

+ +}

+ +

+ +int config_parse_coalesce_sec(

+ +                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) {

+ +        u32_opt *dst = data;

+ +        usec_t usec;

+ +        int r;

+ +

+ +        if (isempty(rvalue)) {

+ +                dst->value = 0;

+ +                dst->set = false;

+ +                return 0;

+ +        }

+ +

+ +        r = parse_sec(rvalue, &usec);

+ +        if (r < 0) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, r,

+ +                           "Failed to parse coalesce setting value, ignoring: %s", rvalue);

+ +                return 0;

+ +        }

+ +

+ +        if (usec > UINT32_MAX) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, 0,

+ +                           "Too large %s= value, ignoring: %s", lvalue, rvalue);

+ +                return 0;

+ +        }

+ +

+ +        if (STR_IN_SET(lvalue, "StatisticsBlockCoalesceSec", "CoalescePacketRateSampleIntervalSec") && usec < 1) {

+ +                log_syntax(unit, LOG_WARNING, filename, line, 0,

+ +                           "Invalid %s= value, ignoring: %s", lvalue, rvalue);

+ +                return 0;

+ +        }

+ +

+ +        dst->value = (uint32_t) usec;

+ +        dst->set = true;

+ +

+ +        return 0;

+ +}

+ +

+ +int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {

+ +        struct ethtool_coalesce ecmd = {

+ +                .cmd = ETHTOOL_GCOALESCE,

+ +        };

+ +        struct ifreq ifr = {

+ +                .ifr_data = (void*) &ecmd,

+ +        };

+ +        bool need_update = false;

+ +        int r;

+ +

+ +        assert(ethtool_fd);

+ +        assert(ifname);

+ +        assert(coalesce);

+ +

+ +        if (coalesce->use_adaptive_rx_coalesce < 0 &&

+ +            coalesce->use_adaptive_tx_coalesce < 0 &&

+ +            !coalesce->rx_coalesce_usecs.set &&

+ +            !coalesce->rx_max_coalesced_frames.set &&

+ +            !coalesce->rx_coalesce_usecs_irq.set &&

+ +            !coalesce->rx_max_coalesced_frames_irq.set &&

+ +            !coalesce->tx_coalesce_usecs.set &&

+ +            !coalesce->tx_max_coalesced_frames.set &&

+ +            !coalesce->tx_coalesce_usecs_irq.set &&

+ +            !coalesce->tx_max_coalesced_frames_irq.set &&

+ +            !coalesce->stats_block_coalesce_usecs.set &&

+ +            !coalesce->pkt_rate_low.set &&

+ +            !coalesce->rx_coalesce_usecs_low.set &&

+ +            !coalesce->rx_max_coalesced_frames_low.set &&

+ +            !coalesce->tx_coalesce_usecs_low.set &&

+ +            !coalesce->tx_max_coalesced_frames_low.set &&

+ +            !coalesce->pkt_rate_high.set &&

+ +            !coalesce->rx_coalesce_usecs_high.set &&

+ +            !coalesce->rx_max_coalesced_frames_high.set &&

+ +            !coalesce->tx_coalesce_usecs_high.set &&

+ +            !coalesce->tx_max_coalesced_frames_high.set &&

+ +            !coalesce->rate_sample_interval.set)

+ +                return 0;

+ +

+ +        r = ethtool_connect(ethtool_fd);

+ +        if (r < 0)

+ +                return r;

+ +

+ +        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +

+ +        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ +        if (r < 0)

+ +                return -errno;

+ +

+ +        if (coalesce->use_adaptive_rx_coalesce >= 0)

+ +                UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);

+ +

+ +        if (coalesce->use_adaptive_tx_coalesce >= 0)

+ +                UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_irq.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_irq.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_irq.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_irq.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);

+ +

+ +        if (coalesce->stats_block_coalesce_usecs.set)

+ +                UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->pkt_rate_low.set)

+ +                UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_low.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_low.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_low.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_low.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);

+ +

+ +        if (coalesce->pkt_rate_high.set)

+ +                UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_high.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_high.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_high.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_high.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);

+ +

+ +        if (coalesce->rate_sample_interval.set)

+ +                UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);

+ +

+ +        if (!need_update)

+ +                return 0;

+ +

+ +        ecmd.cmd = ETHTOOL_SCOALESCE;

+ +        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ +        if (r < 0)

+ +                return -errno;

+ +

+ +        return 0;

+ +}

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index 8fdbdec39a..bb0333775c 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -76,6 +76,31 @@ typedef struct netdev_ring_param {

+          u32_opt tx;

+  } netdev_ring_param;

+  

+ +typedef struct netdev_coalesce_param {

+ +        u32_opt rx_coalesce_usecs;

+ +        u32_opt rx_max_coalesced_frames;

+ +        u32_opt rx_coalesce_usecs_irq;

+ +        u32_opt rx_max_coalesced_frames_irq;

+ +        u32_opt tx_coalesce_usecs;

+ +        u32_opt tx_max_coalesced_frames;

+ +        u32_opt tx_coalesce_usecs_irq;

+ +        u32_opt tx_max_coalesced_frames_irq;

+ +        u32_opt stats_block_coalesce_usecs;

+ +        int use_adaptive_rx_coalesce;

+ +        int use_adaptive_tx_coalesce;

+ +        u32_opt pkt_rate_low;

+ +        u32_opt rx_coalesce_usecs_low;

+ +        u32_opt rx_max_coalesced_frames_low;

+ +        u32_opt tx_coalesce_usecs_low;

+ +        u32_opt tx_max_coalesced_frames_low;

+ +        u32_opt pkt_rate_high;

+ +        u32_opt rx_coalesce_usecs_high;

+ +        u32_opt rx_max_coalesced_frames_high;

+ +        u32_opt tx_coalesce_usecs_high;

+ +        u32_opt tx_max_coalesced_frames_high;

+ +        u32_opt rate_sample_interval;

+ +} netdev_coalesce_param;

+ +

+  int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret);

+  int ethtool_get_link_info(int *ethtool_fd, const char *ifname,

+                            int *ret_autonegotiation, uint64_t *ret_speed,

+ @@ -89,6 +114,7 @@ int ethtool_set_glinksettings(int *ethtool_fd, const char *ifname,

+                                uint64_t speed, Duplex duplex, NetDevPort port);

+  int ethtool_set_channels(int *ethtool_fd, const char *ifname, const netdev_channels *channels);

+  int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg);

+ +int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce);

+  

+  const char *duplex_to_string(Duplex d) _const_;

+  Duplex duplex_from_string(const char *d) _pure_;

+ @@ -106,3 +132,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_wol);

+  CONFIG_PARSER_PROTOTYPE(config_parse_port);

+  CONFIG_PARSER_PROTOTYPE(config_parse_advertise);

+  CONFIG_PARSER_PROTOTYPE(config_parse_ring_buffer_or_channel);

+ +CONFIG_PARSER_PROTOTYPE(config_parse_coalesce_u32);

+ +CONFIG_PARSER_PROTOTYPE(config_parse_coalesce_sec);

+ +CONFIG_PARSER_PROTOTYPE(config_parse_nic_coalesce_setting);

+ diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf

+ index d0190da5cb..f800de8386 100644

+ --- a/src/udev/net/link-config-gperf.gperf

+ +++ b/src/udev/net/link-config-gperf.gperf

+ @@ -21,54 +21,76 @@ struct ConfigPerfItem;

+  %struct-type

+  %includes

+  %%

+ -Match.MACAddress,                      config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

+ -Match.PermanentMACAddress,             config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

+ -Match.OriginalName,                    config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

+ -Match.Path,                            config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

+ -Match.Driver,                          config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

+ -Match.Type,                            config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

+ -Match.Property,                        config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

+ -Match.Host,                            config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

+ -Match.Virtualization,                  config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

+ -Match.KernelCommandLine,               config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

+ -Match.KernelVersion,                   config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

+ -Match.Architecture,                    config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

+ -Link.Description,                      config_parse_string,                   0,                             offsetof(LinkConfig, description)

+ -Link.MACAddressPolicy,                 config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

+ -Link.MACAddress,                       config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

+ -Link.NamePolicy,                       config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

+ -Link.Name,                             config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

+ -Link.AlternativeName,                  config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

+ -Link.AlternativeNamesPolicy,           config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

+ -Link.Alias,                            config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

+ -Link.TransmitQueues,                   config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

+ -Link.ReceiveQueues,                    config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

+ -Link.TransmitQueueLength,              config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

+ -Link.MTUBytes,                         config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

+ -Link.BitsPerSecond,                    config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

+ -Link.Duplex,                           config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

+ -Link.AutoNegotiation,                  config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+ -Link.WakeOnLan,                        config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+ -Link.Port,                             config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ -Link.ReceiveChecksumOffload,           config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RX])

+ -Link.TransmitChecksumOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TX])

+ -Link.GenericSegmentationOffload,       config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+ -Link.TCPSegmentationOffload,           config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+ -Link.TCP6SegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+ -Link.UDPSegmentationOffload,           config_parse_warn_compat,              DISABLED_LEGACY,               0

+ -Link.GenericReceiveOffload,            config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ -Link.LargeReceiveOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ -Link.RxChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ -Link.TxChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ -Link.OtherChannels,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ -Link.CombinedChannels,                 config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+ -Link.Advertise,                        config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ -Link.RxBufferSize,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ -Link.RxMiniBufferSize,                 config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ -Link.RxJumboBufferSize,                config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ -Link.TxBufferSize,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+ -Link.RxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+ -Link.TxFlowControl,                    config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+ -Link.AutoNegotiationFlowControl,       config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ -Link.GenericSegmentOffloadMaxBytes,    config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

+ -Link.GenericSegmentOffloadMaxSegments, config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ +Match.MACAddress,                         config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

+ +Match.PermanentMACAddress,                config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

+ +Match.OriginalName,                       config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

+ +Match.Path,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

+ +Match.Driver,                             config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

+ +Match.Type,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

+ +Match.Property,                           config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

+ +Match.Host,                               config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

+ +Match.Virtualization,                     config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

+ +Match.KernelCommandLine,                  config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

+ +Match.KernelVersion,                      config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

+ +Match.Architecture,                       config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

+ +Link.Description,                         config_parse_string,                   0,                             offsetof(LinkConfig, description)

+ +Link.MACAddressPolicy,                    config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

+ +Link.MACAddress,                          config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

+ +Link.NamePolicy,                          config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

+ +Link.Name,                                config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

+ +Link.AlternativeName,                     config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

+ +Link.AlternativeNamesPolicy,              config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

+ +Link.Alias,                               config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

+ +Link.TransmitQueues,                      config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

+ +Link.ReceiveQueues,                       config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

+ +Link.TransmitQueueLength,                 config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

+ +Link.MTUBytes,                            config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

+ +Link.BitsPerSecond,                       config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

+ +Link.Duplex,                              config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

+ +Link.AutoNegotiation,                     config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+ +Link.WakeOnLan,                           config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+ +Link.Port,                                config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ +Link.ReceiveChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RX])

+ +Link.TransmitChecksumOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TX])

+ +Link.GenericSegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+ +Link.TCPSegmentationOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+ +Link.TCP6SegmentationOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+ +Link.UDPSegmentationOffload,              config_parse_warn_compat,              DISABLED_LEGACY,               0

+ +Link.GenericReceiveOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ +Link.LargeReceiveOffload,                 config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ +Link.RxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ +Link.TxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ +Link.OtherChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ +Link.CombinedChannels,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+ +Link.Advertise,                           config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ +Link.RxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ +Link.RxMiniBufferSize,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ +Link.RxJumboBufferSize,                   config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ +Link.TxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+ +Link.RxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+ +Link.TxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+ +Link.AutoNegotiationFlowControl,          config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ +Link.GenericSegmentOffloadMaxBytes,       config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

+ +Link.GenericSegmentOffloadMaxSegments,    config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ +Link.RxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs)

+ +Link.RxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames)

+ +Link.RxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq)

+ +Link.RxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq)

+ +Link.TxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs)

+ +Link.TxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames)

+ +Link.TxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq)

+ +Link.TxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq)

+ +Link.StatisticsBlockCoalesceSec,          config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs)

+ +Link.UseAdaptiveRxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce)

+ +Link.UseAdaptiveTxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce)

+ +Link.CoalescePacketRateLow,               config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_low)

+ +Link.RxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low)

+ +Link.RxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low)

+ +Link.TxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low)

+ +Link.TxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low)

+ +Link.CoalescePacketRateHigh,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_high)

+ +Link.RxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high)

+ +Link.RxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high)

+ +Link.TxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)

+ +Link.TxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)

+ +Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rate_sample_interval)

+ diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c

+ index 8dfe23691b..9451bd8b66 100644

+ --- a/src/udev/net/link-config.c

+ +++ b/src/udev/net/link-config.c

+ @@ -353,6 +353,10 @@ static int link_config_apply_ethtool_settings(int *ethtool_fd, const LinkConfig

+          if (r < 0)

+                  log_device_warning_errno(device, r, "Could not set flow control, ignoring: %m");

+  

+ +        r = ethtool_set_nic_coalesce_settings(ethtool_fd, name, &config->coalesce);

+ +        if (r < 0)

+ +                log_device_warning_errno(device, r, "Could not set coalesce settings, ignoring: %m");

+ +

+          return 0;

+  }

+  

+ diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h

+ index b505c94f95..8a29a92822 100644

+ --- a/src/udev/net/link-config.h

+ +++ b/src/udev/net/link-config.h

+ @@ -64,6 +64,7 @@ struct LinkConfig {

+          int rx_flow_control;

+          int tx_flow_control;

+          int autoneg_flow_control;

+ +        netdev_coalesce_param coalesce;

+  

+          LIST_FIELDS(LinkConfig, links);

+  };

+ diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link

+ index 112a81930f..5f232ce698 100644

+ --- a/test/fuzz/fuzz-link-parser/directives.link

+ +++ b/test/fuzz/fuzz-link-parser/directives.link

+ @@ -51,3 +51,25 @@ TxFlowControl=

+  AutoNegotiationFlowControl=

+  GenericSegmentOffloadMaxBytes=

+  GenericSegmentOffloadMaxSegments=

+ +RxCoalesceSec=

+ +RxMaxCoalescedFrames=

+ +RxCoalesceIrqSec=

+ +RxMaxCoalescedIrqFrames=

+ +TxCoalesceSec=

+ +TxMaxCoalescedFrames=

+ +TxCoalesceIrqSec=

+ +TxMaxCoalescedIrqFrames=

+ +StatisticsBlockCoalesceSec=

+ +UseAdaptiveRxCoalesce=

+ +UseAdaptiveTxCoalesce=

+ +CoalescePacketRateLow=

+ +RxCoalesceLowSec=

+ +RxMaxCoalescedLowFrames=

+ +TxCoalesceLowSec=

+ +TxMaxCoalescedLowFrames=

+ +CoalescePacketRateHigh=

+ +RxCoalesceHighSec=

+ +RxMaxCoalescedHighFrames=

+ +TxCoalesceHighSec=

+ +TxMaxCoalescedHighFrames=

+ +CoalescePacketRateSampleIntervalSec=

+ -- 

+ 2.31.1

+ 

file added
+96
@@ -0,0 +1,96 @@ 

+ From 0e5c20b7a4f47fd3f8edbc2735810ea3513360bb Mon Sep 17 00:00:00 2001

+ From: Daan De Meyer <daan.j.demeyer@gmail.com>

+ Date: Thu, 19 Aug 2021 13:44:35 +0100

+ Subject: [PATCH] link: Add support for rx-gro-hw nic feature

+ 

+ ---

+  man/systemd.link.xml                       |  7 +++++++

+  src/shared/ethtool-util.c                  | 15 ++++++++-------

+  src/shared/ethtool-util.h                  |  1 +

+  src/udev/net/link-config-gperf.gperf       |  1 +

+  test/fuzz/fuzz-link-parser/directives.link |  1 +

+  5 files changed, 18 insertions(+), 7 deletions(-)

+ 

+ diff --git a/man/systemd.link.xml b/man/systemd.link.xml

+ index 6d8dcb9af7..638a1522cd 100644

+ --- a/man/systemd.link.xml

+ +++ b/man/systemd.link.xml

+ @@ -701,6 +701,13 @@

+            When unset, the kernel's default will be used.</para>

+          </listitem>

+        </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>GenericReceiveOffloadHardware=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, hardware accelerated Generic Receive Offload (GRO) is

+ +          enabled. When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+        <varlistentry>

+          <term><varname>LargeReceiveOffload=</varname></term>

+          <listitem>

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index f7f553dd29..a08bb2b7f5 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -70,13 +70,14 @@ DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);

+  DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");

+  

+  static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {

+ -        [NET_DEV_FEAT_RX]   = "rx-checksum",

+ -        [NET_DEV_FEAT_TX]   = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+ -        [NET_DEV_FEAT_GSO]  = "tx-generic-segmentation",

+ -        [NET_DEV_FEAT_GRO]  = "rx-gro",

+ -        [NET_DEV_FEAT_LRO]  = "rx-lro",

+ -        [NET_DEV_FEAT_TSO]  = "tx-tcp-segmentation",

+ -        [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",

+ +        [NET_DEV_FEAT_RX]     = "rx-checksum",

+ +        [NET_DEV_FEAT_TX]     = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+ +        [NET_DEV_FEAT_GSO]    = "tx-generic-segmentation",

+ +        [NET_DEV_FEAT_GRO]    = "rx-gro",

+ +        [NET_DEV_FEAT_GRO_HW] = "rx-gro-hw",

+ +        [NET_DEV_FEAT_LRO]    = "rx-lro",

+ +        [NET_DEV_FEAT_TSO]    = "tx-tcp-segmentation",

+ +        [NET_DEV_FEAT_TSO6]   = "tx-tcp6-segmentation",

+  };

+  

+  static const char* const ethtool_link_mode_bit_table[] = {

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index bb0333775c..2181ab6fd6 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -23,6 +23,7 @@ typedef enum NetDevFeature {

+          NET_DEV_FEAT_TX,

+          NET_DEV_FEAT_GSO,

+          NET_DEV_FEAT_GRO,

+ +        NET_DEV_FEAT_GRO_HW,

+          NET_DEV_FEAT_LRO,

+          NET_DEV_FEAT_TSO,

+          NET_DEV_FEAT_TSO6,

+ diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf

+ index f800de8386..44b46cb17c 100644

+ --- a/src/udev/net/link-config-gperf.gperf

+ +++ b/src/udev/net/link-config-gperf.gperf

+ @@ -57,6 +57,7 @@ Link.TCPSegmentationOffload,              config_parse_tristate,

+  Link.TCP6SegmentationOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+  Link.UDPSegmentationOffload,              config_parse_warn_compat,              DISABLED_LEGACY,               0

+  Link.GenericReceiveOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ +Link.GenericReceiveOffloadHardware,       config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW])

+  Link.LargeReceiveOffload,                 config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+  Link.RxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+  Link.TxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link

+ index 5f232ce698..b5cffb1a27 100644

+ --- a/test/fuzz/fuzz-link-parser/directives.link

+ +++ b/test/fuzz/fuzz-link-parser/directives.link

+ @@ -36,6 +36,7 @@ TCPSegmentationOffload=

+  TCP6SegmentationOffload=

+  UDPSegmentationOffload=

+  GenericReceiveOffload=

+ +GenericReceiveOffloadHardware=

+  LargeReceiveOffload=

+  RxChannels=

+  TxChannels=

+ -- 

+ 2.31.1

+ 

file added
+127
@@ -0,0 +1,127 @@ 

+ From 0a377494bcfcf4e145e260478071be124d56dc6d Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Fri, 20 Aug 2021 09:41:34 +0900

+ Subject: [PATCH] network: add UseMTU= in [IPv6AcceptRA]

+ 

+ Note that kernel has similar knob in sysctl: accept_ra_mtu.

+ 

+ Closes #18868.

+ ---

+  man/systemd.network.xml                          |  8 ++++++++

+  src/network/networkd-ndisc.c                     | 14 +++++++-------

+  src/network/networkd-network-gperf.gperf         |  1 +

+  src/network/networkd-network.c                   |  3 ++-

+  src/network/networkd-network.h                   |  1 +

+  test/fuzz/fuzz-network-parser/directives.network |  1 +

+  6 files changed, 20 insertions(+), 8 deletions(-)

+ 

+ diff --git a/man/systemd.network.xml b/man/systemd.network.xml

+ index 03100c035b84..573ba959eb4d 100644

+ --- a/man/systemd.network.xml

+ +++ b/man/systemd.network.xml

+ @@ -2265,6 +2265,14 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>

+            </listitem>

+          </varlistentry>

+  

+ +        <varlistentry>

+ +          <term><varname>UseMTU=</varname></term>

+ +          <listitem>

+ +            <para>Takes a boolean. When true, the MTU received in the Router Advertisement will be

+ +            used. Defaults to true.</para>

+ +          </listitem>

+ +        </varlistentry>

+ +

+          <varlistentry>

+            <term><varname>UseAutonomousPrefix=</varname></term>

+            <listitem>

+ diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c

+ index f58edb8f3cae..fe1f1e0333cf 100644

+ --- a/src/network/networkd-ndisc.c

+ +++ b/src/network/networkd-ndisc.c

+ @@ -536,9 +536,9 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {

+  static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {

+          _cleanup_(route_freep) Route *route = NULL;

+          struct in6_addr gateway;

+ -        uint16_t lifetime;

+ +        uint32_t table, mtu = 0;

+          unsigned preference;

+ -        uint32_t table, mtu;

+ +        uint16_t lifetime;

+          usec_t time_now;

+          int r;

+  

+ @@ -575,11 +575,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {

+          if (r < 0)

+                  return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");

+  

+ -        r = sd_ndisc_router_get_mtu(rt, &mtu);

+ -        if (r == -ENODATA)

+ -                mtu = 0;

+ -        else if (r < 0)

+ -                return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");

+ +        if (link->network->ipv6_accept_ra_use_mtu) {

+ +                r = sd_ndisc_router_get_mtu(rt, &mtu);

+ +                if (r < 0 && r != -ENODATA)

+ +                        return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");

+ +        }

+  

+          table = link_get_ipv6_accept_ra_route_table(link);

+  

+ diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf

+ index aa4dc00e55bc..846e54aed759 100644

+ --- a/src/network/networkd-network-gperf.gperf

+ +++ b/src/network/networkd-network-gperf.gperf

+ @@ -256,6 +256,7 @@ IPv6AcceptRA.UseAutonomousPrefix,            config_parse_bool,

+  IPv6AcceptRA.UseOnLinkPrefix,                config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_onlink_prefix)

+  IPv6AcceptRA.UseDNS,                         config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_dns)

+  IPv6AcceptRA.UseDomains,                     config_parse_ipv6_accept_ra_use_domains,                  0,                             offsetof(Network, ipv6_accept_ra_use_domains)

+ +IPv6AcceptRA.UseMTU,                         config_parse_bool,                                        0,                             offsetof(Network, ipv6_accept_ra_use_mtu)

+  IPv6AcceptRA.DHCPv6Client,                   config_parse_ipv6_accept_ra_start_dhcp6_client,           0,                             offsetof(Network, ipv6_accept_ra_start_dhcp6_client)

+  IPv6AcceptRA.RouteTable,                     config_parse_section_route_table,                         0,                             0

+  IPv6AcceptRA.RouteMetric,                    config_parse_dhcp_route_metric,                           0,                             0

+ diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c

+ index bb09ba9e8933..1928db537e0c 100644

+ --- a/src/network/networkd-network.c

+ +++ b/src/network/networkd-network.c

+ @@ -400,15 +400,16 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi

+                  .ipv4_accept_local = -1,

+                  .ipv4_route_localnet = -1,

+                  .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO,

+ -                .ipv6_accept_ra = -1,

+                  .ipv6_dad_transmits = -1,

+                  .ipv6_hop_limit = -1,

+                  .ipv6_proxy_ndp = -1,

+                  .proxy_arp = -1,

+  

+ +                .ipv6_accept_ra = -1,

+                  .ipv6_accept_ra_use_dns = true,

+                  .ipv6_accept_ra_use_autonomous_prefix = true,

+                  .ipv6_accept_ra_use_onlink_prefix = true,

+ +                .ipv6_accept_ra_use_mtu = true,

+                  .ipv6_accept_ra_route_table = RT_TABLE_MAIN,

+                  .ipv6_accept_ra_route_metric = DHCP_ROUTE_METRIC,

+                  .ipv6_accept_ra_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,

+ diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h

+ index 815bcf5023fc..95c86e723040 100644

+ --- a/src/network/networkd-network.h

+ +++ b/src/network/networkd-network.h

+ @@ -301,6 +301,7 @@ struct Network {

+          bool ipv6_accept_ra_use_dns;

+          bool ipv6_accept_ra_use_autonomous_prefix;

+          bool ipv6_accept_ra_use_onlink_prefix;

+ +        bool ipv6_accept_ra_use_mtu;

+          bool active_slave;

+          bool primary_slave;

+          DHCPUseDomains ipv6_accept_ra_use_domains;

+ diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network

+ index 8fe4ced35154..a3711cb77d9c 100644

+ --- a/test/fuzz/fuzz-network-parser/directives.network

+ +++ b/test/fuzz/fuzz-network-parser/directives.network

+ @@ -342,6 +342,7 @@ Label=

+  Prefix=

+  [IPv6AcceptRA]

+  UseDomains=

+ +UseMTU=

+  RouteTable=

+  RouteMetric=

+  UseDNS=

file added
+306
@@ -0,0 +1,306 @@ 

+ From 72328a5977d240d33b78b24e7a6b65b1074000b9 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Thu, 26 Aug 2021 03:31:05 +0900

+ Subject: [PATCH 1/2] ethtool: move function

+ 

+ I'd like to locate all conf parsers at end of file.

+ ---

+  src/shared/ethtool-util.c | 250 +++++++++++++++++++-------------------

+  1 file changed, 125 insertions(+), 125 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index c47d819f0596..af3b917c75cb 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -932,6 +932,131 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au

+          return 0;

+  }

+  

+ +int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {

+ +        struct ethtool_coalesce ecmd = {

+ +                .cmd = ETHTOOL_GCOALESCE,

+ +        };

+ +        struct ifreq ifr = {

+ +                .ifr_data = (void*) &ecmd,

+ +        };

+ +        bool need_update = false;

+ +        int r;

+ +

+ +        assert(ethtool_fd);

+ +        assert(ifname);

+ +        assert(coalesce);

+ +

+ +        if (coalesce->use_adaptive_rx_coalesce < 0 &&

+ +            coalesce->use_adaptive_tx_coalesce < 0 &&

+ +            !coalesce->rx_coalesce_usecs.set &&

+ +            !coalesce->rx_max_coalesced_frames.set &&

+ +            !coalesce->rx_coalesce_usecs_irq.set &&

+ +            !coalesce->rx_max_coalesced_frames_irq.set &&

+ +            !coalesce->tx_coalesce_usecs.set &&

+ +            !coalesce->tx_max_coalesced_frames.set &&

+ +            !coalesce->tx_coalesce_usecs_irq.set &&

+ +            !coalesce->tx_max_coalesced_frames_irq.set &&

+ +            !coalesce->stats_block_coalesce_usecs.set &&

+ +            !coalesce->pkt_rate_low.set &&

+ +            !coalesce->rx_coalesce_usecs_low.set &&

+ +            !coalesce->rx_max_coalesced_frames_low.set &&

+ +            !coalesce->tx_coalesce_usecs_low.set &&

+ +            !coalesce->tx_max_coalesced_frames_low.set &&

+ +            !coalesce->pkt_rate_high.set &&

+ +            !coalesce->rx_coalesce_usecs_high.set &&

+ +            !coalesce->rx_max_coalesced_frames_high.set &&

+ +            !coalesce->tx_coalesce_usecs_high.set &&

+ +            !coalesce->tx_max_coalesced_frames_high.set &&

+ +            !coalesce->rate_sample_interval.set)

+ +                return 0;

+ +

+ +        r = ethtool_connect(ethtool_fd);

+ +        if (r < 0)

+ +                return r;

+ +

+ +        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +

+ +        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ +        if (r < 0)

+ +                return -errno;

+ +

+ +        if (coalesce->use_adaptive_rx_coalesce >= 0)

+ +                UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);

+ +

+ +        if (coalesce->use_adaptive_tx_coalesce >= 0)

+ +                UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_irq.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_irq.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_irq.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_irq.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);

+ +

+ +        if (coalesce->stats_block_coalesce_usecs.set)

+ +                UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);

+ +

+ +        if (coalesce->pkt_rate_low.set)

+ +                UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_low.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_low.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_low.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_low.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);

+ +

+ +        if (coalesce->pkt_rate_high.set)

+ +                UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);

+ +

+ +        if (coalesce->rx_coalesce_usecs_high.set)

+ +                UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);

+ +

+ +        if (coalesce->rx_max_coalesced_frames_high.set)

+ +                UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);

+ +

+ +        if (coalesce->tx_coalesce_usecs_high.set)

+ +                UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);

+ +

+ +        if (coalesce->tx_max_coalesced_frames_high.set)

+ +                UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);

+ +

+ +        if (coalesce->rate_sample_interval.set)

+ +                UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);

+ +

+ +        if (!need_update)

+ +                return 0;

+ +

+ +        ecmd.cmd = ETHTOOL_SCOALESCE;

+ +        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ +        if (r < 0)

+ +                return -errno;

+ +

+ +        return 0;

+ +}

+ +

+  int config_parse_advertise(

+                  const char *unit,

+                  const char *filename,

+ @@ -1182,128 +1307,3 @@ int config_parse_coalesce_sec(

+  

+          return 0;

+  }

+ -

+ -int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {

+ -        struct ethtool_coalesce ecmd = {

+ -                .cmd = ETHTOOL_GCOALESCE,

+ -        };

+ -        struct ifreq ifr = {

+ -                .ifr_data = (void*) &ecmd,

+ -        };

+ -        bool need_update = false;

+ -        int r;

+ -

+ -        assert(ethtool_fd);

+ -        assert(ifname);

+ -        assert(coalesce);

+ -

+ -        if (coalesce->use_adaptive_rx_coalesce < 0 &&

+ -            coalesce->use_adaptive_tx_coalesce < 0 &&

+ -            !coalesce->rx_coalesce_usecs.set &&

+ -            !coalesce->rx_max_coalesced_frames.set &&

+ -            !coalesce->rx_coalesce_usecs_irq.set &&

+ -            !coalesce->rx_max_coalesced_frames_irq.set &&

+ -            !coalesce->tx_coalesce_usecs.set &&

+ -            !coalesce->tx_max_coalesced_frames.set &&

+ -            !coalesce->tx_coalesce_usecs_irq.set &&

+ -            !coalesce->tx_max_coalesced_frames_irq.set &&

+ -            !coalesce->stats_block_coalesce_usecs.set &&

+ -            !coalesce->pkt_rate_low.set &&

+ -            !coalesce->rx_coalesce_usecs_low.set &&

+ -            !coalesce->rx_max_coalesced_frames_low.set &&

+ -            !coalesce->tx_coalesce_usecs_low.set &&

+ -            !coalesce->tx_max_coalesced_frames_low.set &&

+ -            !coalesce->pkt_rate_high.set &&

+ -            !coalesce->rx_coalesce_usecs_high.set &&

+ -            !coalesce->rx_max_coalesced_frames_high.set &&

+ -            !coalesce->tx_coalesce_usecs_high.set &&

+ -            !coalesce->tx_max_coalesced_frames_high.set &&

+ -            !coalesce->rate_sample_interval.set)

+ -                return 0;

+ -

+ -        r = ethtool_connect(ethtool_fd);

+ -        if (r < 0)

+ -                return r;

+ -

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ -

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ -                return -errno;

+ -

+ -        if (coalesce->use_adaptive_rx_coalesce >= 0)

+ -                UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);

+ -

+ -        if (coalesce->use_adaptive_tx_coalesce >= 0)

+ -                UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);

+ -

+ -        if (coalesce->rx_coalesce_usecs.set)

+ -                UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);

+ -

+ -        if (coalesce->rx_max_coalesced_frames.set)

+ -                UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);

+ -

+ -        if (coalesce->rx_coalesce_usecs_irq.set)

+ -                UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);

+ -

+ -        if (coalesce->rx_max_coalesced_frames_irq.set)

+ -                UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);

+ -

+ -        if (coalesce->tx_coalesce_usecs.set)

+ -                UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);

+ -

+ -        if (coalesce->tx_max_coalesced_frames.set)

+ -                UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);

+ -

+ -        if (coalesce->tx_coalesce_usecs_irq.set)

+ -                UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);

+ -

+ -        if (coalesce->tx_max_coalesced_frames_irq.set)

+ -                UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);

+ -

+ -        if (coalesce->stats_block_coalesce_usecs.set)

+ -                UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);

+ -

+ -        if (coalesce->pkt_rate_low.set)

+ -                UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);

+ -

+ -        if (coalesce->rx_coalesce_usecs_low.set)

+ -                UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);

+ -

+ -        if (coalesce->rx_max_coalesced_frames_low.set)

+ -                UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);

+ -

+ -        if (coalesce->tx_coalesce_usecs_low.set)

+ -                UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);

+ -

+ -        if (coalesce->tx_max_coalesced_frames_low.set)

+ -                UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);

+ -

+ -        if (coalesce->pkt_rate_high.set)

+ -                UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);

+ -

+ -        if (coalesce->rx_coalesce_usecs_high.set)

+ -                UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);

+ -

+ -        if (coalesce->rx_max_coalesced_frames_high.set)

+ -                UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);

+ -

+ -        if (coalesce->tx_coalesce_usecs_high.set)

+ -                UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);

+ -

+ -        if (coalesce->tx_max_coalesced_frames_high.set)

+ -                UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);

+ -

+ -        if (coalesce->rate_sample_interval.set)

+ -                UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);

+ -

+ -        if (!need_update)

+ -                return 0;

+ -

+ -        ecmd.cmd = ETHTOOL_SCOALESCE;

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ -                return -errno;

+ -

+ -        return 0;

+ -}

+ 

+ From ee7512404b5de7c5ac36e09436379fada2ed84e7 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Thu, 26 Aug 2021 03:34:23 +0900

+ Subject: [PATCH 2/2] udev/net: initialize coalesce tristate variables

+ 

+ Otherwise, 99-default.link may introduce something like the

+ following warnings:

+ ----

+ Aug 26 03:23:59 systemd-udevd[519]: wlan0: Could not set coalesce settings, ignoring: Operation not supported

+ Aug 26 03:24:00 systemd-udevd[547]: wlp59s0: Could not set coalesce settings, ignoring: Operation not supported

+ ----

+ 

+ Follow-up for 6c35ea5ef0231d519ff24d43a57a72cebab6a121.

+ ---

+  src/udev/net/link-config.c | 2 ++

+  1 file changed, 2 insertions(+)

+ 

+ diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c

+ index 69f651435034..4963ba2fae81 100644

+ --- a/src/udev/net/link-config.c

+ +++ b/src/udev/net/link-config.c

+ @@ -142,6 +142,8 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {

+                  .tx_flow_control = -1,

+                  .autoneg_flow_control = -1,

+                  .txqueuelen = UINT32_MAX,

+ +                .coalesce.use_adaptive_rx_coalesce = -1,

+ +                .coalesce.use_adaptive_tx_coalesce = -1,

+          };

+  

+          for (i = 0; i < ELEMENTSOF(link->features); i++)

@@ -0,0 +1,336 @@ 

+ From 0b9f08931944c2e33c6ed012919157e429eb7be2 Mon Sep 17 00:00:00 2001

+ From: Antony Deepak Thomas <antonydeepak@gmail.com>

+ Date: Wed, 29 Sep 2021 12:47:49 +0900

+ Subject: [PATCH 1/4] fileio: introduce read_virtual_file_fd()

+ 

+ ---

+  src/basic/fileio.c | 24 ++++++++++++++++--------

+  src/basic/fileio.h |  1 +

+  2 files changed, 17 insertions(+), 8 deletions(-)

+ 

+ diff --git a/src/basic/fileio.c b/src/basic/fileio.c

+ index 466c6321c7..4a0d060105 100644

+ --- a/src/basic/fileio.c

+ +++ b/src/basic/fileio.c

+ @@ -373,9 +373,8 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {

+          return 1;

+  }

+  

+ -int read_virtual_file(const char *filename, size_t max_size, char **ret_contents, size_t *ret_size) {

+ +int read_virtual_file_fd(int fd, size_t max_size, char **ret_contents, size_t *ret_size) {

+          _cleanup_free_ char *buf = NULL;

+ -        _cleanup_close_ int fd = -1;

+          size_t n, size;

+          int n_retries;

+          bool truncated = false;

+ @@ -393,10 +392,7 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents

+           * contents* may be returned. (Though the read is still done using one syscall.) Returns 0 on

+           * partial success, 1 if untruncated contents were read. */

+  

+ -        fd = open(filename, O_RDONLY|O_CLOEXEC);

+ -        if (fd < 0)

+ -                return -errno;

+ -

+ +        assert(fd >= 0);

+          assert(max_size <= READ_VIRTUAL_BYTES_MAX || max_size == SIZE_MAX);

+  

+          /* Limit the number of attempts to read the number of bytes returned by fstat(). */

+ @@ -432,8 +428,8 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents

+  

+                          n_retries--;

+                  } else if (n_retries > 1) {

+ -                        /* Files in /proc are generally smaller than the page size so let's start with a page size

+ -                         * buffer from malloc and only use the max buffer on the final try. */

+ +                        /* Files in /proc are generally smaller than the page size so let's start with

+ +                         * a page size buffer from malloc and only use the max buffer on the final try. */

+                          size = MIN3(page_size() - 1, READ_VIRTUAL_BYTES_MAX, max_size);

+                          n_retries = 1;

+                  } else {

+ @@ -517,6 +513,18 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents

+          return !truncated;

+  }

+  

+ +int read_virtual_file(const char *filename, size_t max_size, char **ret_contents, size_t *ret_size) {

+ +        _cleanup_close_ int fd = -1;

+ +

+ +        assert(filename);

+ +

+ +        fd = open(filename, O_RDONLY | O_NOCTTY | O_CLOEXEC);

+ +        if (fd < 0)

+ +                return -errno;

+ +

+ +        return read_virtual_file_fd(fd, max_size, ret_contents, ret_size);

+ +}

+ +

+  int read_full_stream_full(

+                  FILE *f,

+                  const char *filename,

+ diff --git a/src/basic/fileio.h b/src/basic/fileio.h

+ index 9bd2037f5b..82330840bf 100644

+ --- a/src/basic/fileio.h

+ +++ b/src/basic/fileio.h

+ @@ -66,6 +66,7 @@ static inline int read_full_file(const char *filename, char **ret_contents, size

+          return read_full_file_full(AT_FDCWD, filename, UINT64_MAX, SIZE_MAX, 0, NULL, ret_contents, ret_size);

+  }

+  

+ +int read_virtual_file_fd(int fd, size_t max_size, char **ret_contents, size_t *ret_size);

+  int read_virtual_file(const char *filename, size_t max_size, char **ret_contents, size_t *ret_size);

+  static inline int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) {

+          return read_virtual_file(filename, SIZE_MAX, ret_contents, ret_size);

+ -- 

+ 2.31.1

+ 

+ 

+ From bede594fa1ea4c32a886191b774134effcf71bef Mon Sep 17 00:00:00 2001

+ From: Antony Deepak Thomas <antonydeepak@gmail.com>

+ Date: Wed, 29 Sep 2021 12:57:30 +0900

+ Subject: [PATCH 2/4] string-util: introduce streq_skip_trailing_chars()

+ 

+ ---

+  src/basic/string-util.c     | 16 ++++++++++++++++

+  src/basic/string-util.h     |  2 ++

+  src/test/test-string-util.c | 28 ++++++++++++++++++++++++++++

+  3 files changed, 46 insertions(+)

+ 

+ diff --git a/src/basic/string-util.c b/src/basic/string-util.c

+ index a645958d38..6ceaeaf9df 100644

+ --- a/src/basic/string-util.c

+ +++ b/src/basic/string-util.c

+ @@ -1146,3 +1146,19 @@ int string_contains_word_strv(const char *string, const char *separators, char *

+                  *ret_word = found;

+          return !!found;

+  }

+ +

+ +bool streq_skip_trailing_chars(const char *s1, const char *s2, const char *ok) {

+ +        if (!s1 && !s2)

+ +                return true;

+ +        if (!s1 || !s2)

+ +                return false;

+ +

+ +        if (!ok)

+ +                ok = WHITESPACE;

+ +

+ +        for (; *s1 && *s2; s1++, s2++)

+ +                if (*s1 != *s2)

+ +                        break;

+ +

+ +        return in_charset(s1, ok) && in_charset(s2, ok);

+ +}

+ diff --git a/src/basic/string-util.h b/src/basic/string-util.h

+ index 9155e50ba8..0bf215827e 100644

+ --- a/src/basic/string-util.h

+ +++ b/src/basic/string-util.h

+ @@ -242,3 +242,5 @@ int string_contains_word_strv(const char *string, const char *separators, char *

+  static inline int string_contains_word(const char *string, const char *separators, const char *word) {

+          return string_contains_word_strv(string, separators, STRV_MAKE(word), NULL);

+  }

+ +

+ +bool streq_skip_trailing_chars(const char *s1, const char *s2, const char *ok);

+ diff --git a/src/test/test-string-util.c b/src/test/test-string-util.c

+ index 4d9d0260c9..9a9c974332 100644

+ --- a/src/test/test-string-util.c

+ +++ b/src/test/test-string-util.c

+ @@ -1000,6 +1000,33 @@ static void test_strextendf(void) {

+          assert_se(streq(p, "<77>,<99>,<                                                                              88>,<00001234>"));

+  }

+  

+ +static void test_streq_skip_trailing_chars(void) {

+ +        log_info("/* %s */", __func__);

+ +

+ +        /* NULL is WHITESPACE by default*/

+ +        assert_se(streq_skip_trailing_chars("foo bar", "foo bar", NULL));

+ +        assert_se(streq_skip_trailing_chars("foo", "foo", NULL));

+ +        assert_se(streq_skip_trailing_chars("foo bar      ", "foo bar", NULL));

+ +        assert_se(streq_skip_trailing_chars("foo bar", "foo bar\t\t", NULL));

+ +        assert_se(streq_skip_trailing_chars("foo bar  ", "foo bar\t\t", NULL));

+ +        assert_se(streq_skip_trailing_chars("foo\nbar", "foo\nbar", NULL));

+ +        assert_se(streq_skip_trailing_chars("\t\tfoo bar", "\t\tfoo bar", NULL));

+ +        assert_se(streq_skip_trailing_chars(" foo bar\t", " foo bar\n", NULL));

+ +

+ +        assert_se(!streq_skip_trailing_chars("foobar", "foo bar", NULL));

+ +        assert_se(!streq_skip_trailing_chars("foo\nbar", "foo\tbar", NULL));

+ +        assert_se(!streq_skip_trailing_chars("\t\nfoo bar", "\t foo bar", NULL));

+ +

+ +        assert_se(streq_skip_trailing_chars("foo bar      ", "foo bar", WHITESPACE));

+ +        assert_se(!streq_skip_trailing_chars("foo bar      ", "foo bar", NEWLINE));

+ +

+ +        assert_se(streq_skip_trailing_chars(NULL, NULL, NULL));

+ +        assert_se(streq_skip_trailing_chars("", "", NULL));

+ +        assert_se(!streq_skip_trailing_chars(NULL, "foo bar", NULL));

+ +        assert_se(!streq_skip_trailing_chars("foo", NULL, NULL));

+ +        assert_se(!streq_skip_trailing_chars("", "f", NULL));

+ +}

+ +

+  int main(int argc, char *argv[]) {

+          test_setup_logging(LOG_DEBUG);

+  

+ @@ -1039,6 +1066,7 @@ int main(int argc, char *argv[]) {

+          test_string_contains_word();

+          test_strverscmp_improved();

+          test_strextendf();

+ +        test_streq_skip_trailing_chars();

+  

+          return 0;

+  }

+ -- 

+ 2.31.1

+ 

+ 

+ From a2552e17829d0090db3ff5f2e6f2d772d0fca3e9 Mon Sep 17 00:00:00 2001

+ From: Antony Deepak Thomas <antonydeepak@gmail.com>

+ Date: Wed, 29 Sep 2021 13:06:25 +0900

+ Subject: [PATCH 3/4] fileio: introduce new mode to suppress writing the same

+  value

+ 

+ ---

+  src/basic/fileio.c | 29 +++++++++++++++++++++++++++--

+  src/basic/fileio.h | 23 ++++++++++++-----------

+  2 files changed, 39 insertions(+), 13 deletions(-)

+ 

+ diff --git a/src/basic/fileio.c b/src/basic/fileio.c

+ index 4a0d060105..729789ce47 100644

+ --- a/src/basic/fileio.c

+ +++ b/src/basic/fileio.c

+ @@ -146,6 +146,30 @@ int write_string_stream_ts(

+                          return -EBADF;

+          }

+  

+ +        if (flags & WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) {

+ +                _cleanup_free_ char *t = NULL;

+ +

+ +                /* If value to be written is same as that of the existing value, then suppress the write. */

+ +

+ +                if (fd < 0) {

+ +                        fd = fileno(f);

+ +                        if (fd < 0)

+ +                                return -EBADF;

+ +                }

+ +

+ +                /* Read an additional byte to detect cases where the prefix matches but the rest

+ +                 * doesn't. Also, 0 returned by read_virtual_file_fd() means the read was truncated and

+ +                 * it won't be equal to the new value. */

+ +                if (read_virtual_file_fd(fd, strlen(line)+1, &t, NULL) > 0 &&

+ +                    streq_skip_trailing_chars(line, t, NEWLINE)) {

+ +                        log_debug("No change in value '%s', supressing write", line);

+ +                        return 0;

+ +                }

+ +

+ +                if (lseek(fd, 0, SEEK_SET) < 0)

+ +                        return -errno;

+ +        }

+ +

+          needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");

+  

+          if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {

+ @@ -261,10 +285,11 @@ int write_string_file_ts(

+                  assert(!ts);

+  

+          /* We manually build our own version of fopen(..., "we") that works without O_CREAT and with O_NOFOLLOW if needed. */

+ -        fd = open(fn, O_WRONLY|O_CLOEXEC|O_NOCTTY |

+ +        fd = open(fn, O_CLOEXEC|O_NOCTTY |

+                    (FLAGS_SET(flags, WRITE_STRING_FILE_NOFOLLOW) ? O_NOFOLLOW : 0) |

+                    (FLAGS_SET(flags, WRITE_STRING_FILE_CREATE) ? O_CREAT : 0) |

+ -                  (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0),

+ +                  (FLAGS_SET(flags, WRITE_STRING_FILE_TRUNCATE) ? O_TRUNC : 0) |

+ +                  (FLAGS_SET(flags, WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL) ? O_RDWR : O_WRONLY),

+                    (FLAGS_SET(flags, WRITE_STRING_FILE_MODE_0600) ? 0600 : 0666));

+          if (fd < 0) {

+                  r = -errno;

+ diff --git a/src/basic/fileio.h b/src/basic/fileio.h

+ index 82330840bf..a72b2f3881 100644

+ --- a/src/basic/fileio.h

+ +++ b/src/basic/fileio.h

+ @@ -15,17 +15,18 @@

+  #define LONG_LINE_MAX (1U*1024U*1024U)

+  

+  typedef enum {

+ -        WRITE_STRING_FILE_CREATE                = 1 << 0,

+ -        WRITE_STRING_FILE_TRUNCATE              = 1 << 1,

+ -        WRITE_STRING_FILE_ATOMIC                = 1 << 2,

+ -        WRITE_STRING_FILE_AVOID_NEWLINE         = 1 << 3,

+ -        WRITE_STRING_FILE_VERIFY_ON_FAILURE     = 1 << 4,

+ -        WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE = 1 << 5,

+ -        WRITE_STRING_FILE_SYNC                  = 1 << 6,

+ -        WRITE_STRING_FILE_DISABLE_BUFFER        = 1 << 7,

+ -        WRITE_STRING_FILE_NOFOLLOW              = 1 << 8,

+ -        WRITE_STRING_FILE_MKDIR_0755            = 1 << 9,

+ -        WRITE_STRING_FILE_MODE_0600             = 1 << 10,

+ +        WRITE_STRING_FILE_CREATE                     = 1 << 0,

+ +        WRITE_STRING_FILE_TRUNCATE                   = 1 << 1,

+ +        WRITE_STRING_FILE_ATOMIC                     = 1 << 2,

+ +        WRITE_STRING_FILE_AVOID_NEWLINE              = 1 << 3,

+ +        WRITE_STRING_FILE_VERIFY_ON_FAILURE          = 1 << 4,

+ +        WRITE_STRING_FILE_VERIFY_IGNORE_NEWLINE      = 1 << 5,

+ +        WRITE_STRING_FILE_SYNC                       = 1 << 6,

+ +        WRITE_STRING_FILE_DISABLE_BUFFER             = 1 << 7,

+ +        WRITE_STRING_FILE_NOFOLLOW                   = 1 << 8,

+ +        WRITE_STRING_FILE_MKDIR_0755                 = 1 << 9,

+ +        WRITE_STRING_FILE_MODE_0600                  = 1 << 10,

+ +        WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL = 1 << 11,

+  

+          /* And before you wonder, why write_string_file_atomic_label_ts() is a separate function instead of just one

+             more flag here: it's about linking: we don't want to pull -lselinux into all users of write_string_file()

+ -- 

+ 2.31.1

+ 

+ 

+ From 41d86b627331f432454280714dd5b17d255367ba Mon Sep 17 00:00:00 2001

+ From: Antony Deepak Thomas <antonydeepak@gmail.com>

+ Date: Wed, 29 Sep 2021 13:07:42 +0900

+ Subject: [PATCH 4/4] sysctl-util: minimize side-effects when running

+  `systemd-sysctl`

+ 

+ Currently `systemd-sysctl` binary is used in `systemd-sysctl.service`

+ which is mostly configured as `oneshot`. There are situations where one

+ would like to use systemd to maintain Sysctl configurations on a host,

+ using a configuration managers such as Chef or Puppet, by apply

+ configurations every X duration.

+ The problem with using `systemd-sysctl` is that it writes all the Sysctl

+ settings, even if the values for those settings have not changed. From

+ experience, we have observed that some Sysctl settings cause actions in

+ the kernel upon writing(like dropping caches) which in turn cause

+ undesired side effects.

+ This patch tries to minimize such side effects by comparing values

+ before writing.

+ ---

+  src/basic/sysctl-util.c | 19 +++++--------------

+  1 file changed, 5 insertions(+), 14 deletions(-)

+ 

+ diff --git a/src/basic/sysctl-util.c b/src/basic/sysctl-util.c

+ index 8913e6ff85..4da3eaf5f7 100644

+ --- a/src/basic/sysctl-util.c

+ +++ b/src/basic/sysctl-util.c

+ @@ -44,25 +44,16 @@ char *sysctl_normalize(char *s) {

+  

+  int sysctl_write(const char *property, const char *value) {

+          char *p;

+ -        _cleanup_close_ int fd = -1;

+ -

+          assert(property);

+          assert(value);

+ -

+ -        log_debug("Setting '%s' to '%.*s'.", property, (int) strcspn(value, NEWLINE), value);

+ -

+          p = strjoina("/proc/sys/", property);

+ -        fd = open(p, O_WRONLY|O_CLOEXEC);

+ -        if (fd < 0)

+ -                return -errno;

+ +        path_simplify(p);

+ +        if (!path_is_normalized(p))

+ +                return -EINVAL;

+  

+ -        if (!endswith(value, "\n"))

+ -                value = strjoina(value, "\n");

+ -

+ -        if (write(fd, value, strlen(value)) < 0)

+ -                return -errno;

+ +        log_debug("Setting '%s' to '%s'", p, value);

+  

+ -        return 0;

+ +        return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER | WRITE_STRING_FILE_SUPPRESS_REDUNDANT_VIRTUAL);

+  }

+  

+  int sysctl_writef(const char *property, const char *format, ...) {

+ -- 

+ 2.31.1

+ 

file added
+927
@@ -0,0 +1,927 @@ 

+ From 6d9a72f3b9b4d00ec80051503e5e3d4d7cd46c05 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Wed, 15 Sep 2021 01:28:29 +0900

+ Subject: [PATCH 1/5] ethtool-util: use sizeof()

+ 

+ ---

+  src/shared/ethtool-util.c | 20 ++++++++++----------

+  1 file changed, 10 insertions(+), 10 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index af3b917c75cb..d1f5eac63334 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -214,7 +214,7 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -254,7 +254,7 @@ int ethtool_get_link_info(

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -303,7 +303,7 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -362,7 +362,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -405,7 +405,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -538,7 +538,7 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = get_stringset(*ethtool_fd, &ifr, ETH_SS_FEATURES, &strings);

+          if (r < 0)

+ @@ -787,7 +787,7 @@ int ethtool_set_glinksettings(

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = get_glinksettings(*fd, &ifr, &u);

+          if (r < 0) {

+ @@ -857,7 +857,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -906,7 +906,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ @@ -974,7 +974,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+          if (r < 0)

+ 

+ From 4253dab576b3ff17887c3e0d97380aab2aa29d82 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Wed, 15 Sep 2021 01:41:15 +0900

+ Subject: [PATCH 2/5] ethtool-util: shorten code a bit

+ 

+ Also fixes a error code in debugging log.

+ ---

+  src/shared/ethtool-util.c | 70 ++++++++++++---------------------------

+  1 file changed, 22 insertions(+), 48 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index d1f5eac63334..ac21ef0f61a8 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -216,8 +216,7 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) {

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (isempty(ecmd.driver))

+ @@ -256,8 +255,7 @@ int ethtool_get_link_info(

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (ret_autonegotiation)

+ @@ -305,8 +303,7 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (epaddr.addr.size != 6)

+ @@ -364,8 +361,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          UPDATE(ecmd.wolopts, wolopts, need_update);

+ @@ -374,8 +370,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {

+                  return 0;

+  

+          ecmd.cmd = ETHTOOL_SWOL;

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -407,8 +402,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (ring->rx.set)

+ @@ -427,8 +421,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+                  return 0;

+  

+          ecmd.cmd = ETHTOOL_SRINGPARAM;

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -446,7 +439,6 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st

+                  },

+          };

+          unsigned len;

+ -        int r;

+  

+          assert(ethtool_fd >= 0);

+          assert(ifr);

+ @@ -454,8 +446,7 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st

+  

+          ifr->ifr_data = (void *) &buffer.info;

+  

+ -        r = ioctl(ethtool_fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          if (!buffer.info.sset_mask)

+ @@ -478,8 +469,7 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st

+  

+          ifr->ifr_data = (void *) strings;

+  

+ -        r = ioctl(ethtool_fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          *ret = TAKE_PTR(strings);

+ @@ -559,9 +549,8 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+  

+          ifr.ifr_data = (void *) sfeatures;

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ -                return log_debug_errno(r, "ethtool: could not set ethtool features for %s", ifname);

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+ +                return log_debug_errno(errno, "ethtool: could not set ethtool features for %s", ifname);

+  

+          return 0;

+  }

+ @@ -575,7 +564,6 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset

+          };

+          struct ethtool_link_usettings *u;

+          unsigned offset;

+ -        int r;

+  

+          assert(fd >= 0);

+          assert(ifr);

+ @@ -591,8 +579,7 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset

+  

+          ifr->ifr_data = (void *) &ecmd;

+  

+ -        r = ioctl(fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)

+ @@ -602,8 +589,7 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset

+  

+          ifr->ifr_data = (void *) &ecmd;

+  

+ -        r = ioctl(fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)

+ @@ -636,7 +622,6 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r

+          struct ethtool_cmd ecmd = {

+                  .cmd = ETHTOOL_GSET,

+          };

+ -        int r;

+  

+          assert(fd >= 0);

+          assert(ifr);

+ @@ -644,8 +629,7 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r

+  

+          ifr->ifr_data = (void *) &ecmd;

+  

+ -        r = ioctl(fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          e = new(struct ethtool_link_usettings, 1);

+ @@ -678,7 +662,6 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin

+                  __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];

+          } ecmd = {};

+          unsigned offset;

+ -        int r;

+  

+          assert(fd >= 0);

+          assert(ifr);

+ @@ -700,8 +683,7 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin

+  

+          ifr->ifr_data = (void *) &ecmd;

+  

+ -        r = ioctl(fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -711,7 +693,6 @@ static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettin

+          struct ethtool_cmd ecmd = {

+                  .cmd = ETHTOOL_SSET,

+          };

+ -        int r;

+  

+          assert(fd >= 0);

+          assert(ifr);

+ @@ -736,8 +717,7 @@ static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettin

+  

+          ifr->ifr_data = (void *) &ecmd;

+  

+ -        r = ioctl(fd, SIOCETHTOOL, ifr);

+ -        if (r < 0)

+ +        if (ioctl(fd, SIOCETHTOOL, ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -859,8 +839,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (channels->rx.set)

+ @@ -879,8 +858,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha

+                  return 0;

+  

+          ecmd.cmd = ETHTOOL_SCHANNELS;

+ -        r = ioctl(*fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -908,8 +886,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (rx >= 0)

+ @@ -925,8 +902,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au

+                  return 0;

+  

+          ecmd.cmd = ETHTOOL_SPAUSEPARAM;

+ -        r = ioctl(*fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ @@ -976,8 +952,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const

+  

+          strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          if (coalesce->use_adaptive_rx_coalesce >= 0)

+ @@ -1050,8 +1025,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const

+                  return 0;

+  

+          ecmd.cmd = ETHTOOL_SCOALESCE;

+ -        r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);

+ -        if (r < 0)

+ +        if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          return 0;

+ 

+ From 008d3a370ccdea13290ab9277b32cc582b886b17 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Tue, 14 Sep 2021 17:42:52 +0900

+ Subject: [PATCH 3/5] ethtool: do not set unavailable or never_changed bits

+ 

+ ---

+  src/shared/ethtool-util.c | 138 ++++++++++++++++++++++++++------------

+  1 file changed, 96 insertions(+), 42 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index ac21ef0f61a8..59b1bd86f085 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -427,30 +427,31 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde

+          return 0;

+  }

+  

+ -static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **ret) {

+ +static int get_stringset(int ethtool_fd, const char *ifname, enum ethtool_stringset stringset_id, struct ethtool_gstrings **ret) {

+          _cleanup_free_ struct ethtool_gstrings *strings = NULL;

+          struct {

+                  struct ethtool_sset_info info;

+                  uint32_t space;

+          } buffer = {

+ -                .info = {

+ -                        .cmd = ETHTOOL_GSSET_INFO,

+ -                        .sset_mask = UINT64_C(1) << stringset_id,

+ -                },

+ +                .info.cmd = ETHTOOL_GSSET_INFO,

+ +                .info.sset_mask = UINT64_C(1) << stringset_id,

+          };

+ -        unsigned len;

+ +        struct ifreq ifr = {

+ +                .ifr_data = (void*) &buffer,

+ +        };

+ +        uint32_t len;

+  

+          assert(ethtool_fd >= 0);

+ -        assert(ifr);

+ +        assert(ifname);

+          assert(ret);

+  

+ -        ifr->ifr_data = (void *) &buffer.info;

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+ -        if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0)

+ +        if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+ -        if (!buffer.info.sset_mask)

+ -                return -EINVAL;

+ +        if (buffer.info.sset_mask == 0)

+ +                return -EOPNOTSUPP;

+  

+  #pragma GCC diagnostic push

+  #if HAVE_ZERO_LENGTH_BOUNDS

+ @@ -458,8 +459,10 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st

+  #endif

+          len = buffer.info.data[0];

+  #pragma GCC diagnostic pop

+ +        if (len == 0)

+ +                return -EOPNOTSUPP;

+  

+ -        strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN);

+ +        strings = malloc0(offsetof(struct ethtool_gstrings, data) + len * ETH_GSTRING_LEN);

+          if (!strings)

+                  return -ENOMEM;

+  

+ @@ -467,47 +470,92 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st

+          strings->string_set = stringset_id;

+          strings->len = len;

+  

+ -        ifr->ifr_data = (void *) strings;

+ +        ifr.ifr_data = (void*) strings;

+  

+ -        if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0)

+ +        if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return -errno;

+  

+          *ret = TAKE_PTR(strings);

+ +        return 0;

+ +}

+ +

+ +static int get_features(int ethtool_fd, const char *ifname, uint32_t n_features, struct ethtool_gfeatures **ret) {

+ +        _cleanup_free_ struct ethtool_gfeatures *gfeatures = NULL;

+ +        struct ifreq ifr;

+ +

+ +        assert(ethtool_fd >= 0);

+ +        assert(ifname);

+ +        assert(ret);

+ +        assert(n_features > 0);

+ +

+ +        gfeatures = malloc0(offsetof(struct ethtool_gfeatures, features) +

+ +                            DIV_ROUND_UP(n_features, 32U) * sizeof(gfeatures->features[0]));

+ +        if (!gfeatures)

+ +                return -ENOMEM;

+ +

+ +        gfeatures->cmd = ETHTOOL_GFEATURES;

+ +        gfeatures->size = DIV_ROUND_UP(n_features, 32U);

+ +

+ +        ifr = (struct ifreq) {

+ +                .ifr_data = (void*) gfeatures,

+ +        };

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+ +

+ +        if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+ +                return -errno;

+  

+ +        *ret = TAKE_PTR(gfeatures);

+          return 0;

+  }

+  

+  static int set_features_bit(

+                  const struct ethtool_gstrings *strings,

+ +                const struct ethtool_gfeatures *gfeatures,

+ +                struct ethtool_sfeatures *sfeatures,

+                  const char *feature,

+ -                bool flag,

+ -                struct ethtool_sfeatures *sfeatures) {

+ +                int flag) {

+ +

+          bool found = false;

+ +        int r = -ENODATA;

+  

+          assert(strings);

+ -        assert(feature);

+ +        assert(gfeatures);

+          assert(sfeatures);

+ +        assert(feature);

+ +

+ +        if (flag < 0)

+ +                return 0;

+ +

+ +        for (uint32_t i = 0; i < strings->len; i++) {

+ +                uint32_t block, mask;

+  

+ -        for (size_t i = 0; i < strings->len; i++)

+ -                if (streq((char *) &strings->data[i * ETH_GSTRING_LEN], feature) ||

+ -                    (endswith(feature, "-") && startswith((char *) &strings->data[i * ETH_GSTRING_LEN], feature))) {

+ -                        size_t block, bit;

+ +                if (!strneq((const char*) &strings->data[i * ETH_GSTRING_LEN], feature, ETH_GSTRING_LEN) &&

+ +                    !(endswith(feature, "-") && startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature)))

+ +                        continue;

+  

+ -                        block = i / 32;

+ -                        bit = i % 32;

+ +                block = i / 32;

+ +                mask = UINT32_C(1) << (i % 32);

+  

+ -                        sfeatures->features[block].valid |= 1 << bit;

+ -                        SET_FLAG(sfeatures->features[block].requested, 1 << bit, flag);

+ -                        found = true;

+ +                if (!FLAGS_SET(gfeatures->features[block].available, mask) ||

+ +                    FLAGS_SET(gfeatures->features[block].never_changed, mask)) {

+ +                        r = -EOPNOTSUPP;

+ +                        continue;

+                  }

+  

+ -        return found ? 0 : -ENODATA;

+ +                sfeatures->features[block].valid |= mask;

+ +                SET_FLAG(sfeatures->features[block].requested, mask, flag);

+ +

+ +                found = true;

+ +        }

+ +

+ +        return found ? 0 : r;

+  }

+  

+  int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]) {

+          _cleanup_free_ struct ethtool_gstrings *strings = NULL;

+ -        struct ethtool_sfeatures *sfeatures;

+ -        struct ifreq ifr = {};

+ +        _cleanup_free_ struct ethtool_gfeatures *gfeatures = NULL;

+ +        _cleanup_free_ struct ethtool_sfeatures *sfeatures = NULL;

+ +        struct ifreq ifr;

+          bool have = false;

+          int r;

+  

+ @@ -528,26 +576,32 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+          if (r < 0)

+                  return r;

+  

+ -        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+ +        r = get_stringset(*ethtool_fd, ifname, ETH_SS_FEATURES, &strings);

+ +        if (r < 0)

+ +                return log_debug_errno(r, "ethtool: could not get ethtool feature strings: %m");

+  

+ -        r = get_stringset(*ethtool_fd, &ifr, ETH_SS_FEATURES, &strings);

+ +        r = get_features(*ethtool_fd, ifname, strings->len, &gfeatures);

+          if (r < 0)

+ -                return log_debug_errno(r, "ethtool: could not get ethtool features for %s", ifname);

+ +                return log_debug_errno(r, "ethtool: could not get ethtool features for %s: %m", ifname);

+ +

+ +        sfeatures = malloc0(offsetof(struct ethtool_sfeatures, features) +

+ +                            DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0]));

+ +        if (!sfeatures)

+ +                return log_oom_debug();

+  

+ -        sfeatures = alloca0(sizeof(struct ethtool_sfeatures) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0]));

+          sfeatures->cmd = ETHTOOL_SFEATURES;

+          sfeatures->size = DIV_ROUND_UP(strings->len, 32U);

+  

+ -        for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++)

+ -                if (features[i] >= 0) {

+ -                        r = set_features_bit(strings, netdev_feature_table[i], features[i], sfeatures);

+ -                        if (r < 0) {

+ -                                log_debug_errno(r, "ethtool: could not find feature, ignoring: %s", netdev_feature_table[i]);

+ -                                continue;

+ -                        }

+ -                }

+ +        for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) {

+ +                r = set_features_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]);

+ +                if (r < 0)

+ +                        log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname);

+ +        }

+  

+ -        ifr.ifr_data = (void *) sfeatures;

+ +        ifr = (struct ifreq) {

+ +                .ifr_data = (void*) sfeatures,

+ +        };

+ +        strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname);

+  

+          if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0)

+                  return log_debug_errno(errno, "ethtool: could not set ethtool features for %s", ifname);

+ 

+ From 7a4f203547c62cdc7611f38d97058b530570048f Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Wed, 15 Sep 2021 01:48:59 +0900

+ Subject: [PATCH 4/5] ethtool-util: apply tx-checksum-* features at last

+ 

+ NET_DEV_FEAT_TX matches multiple features. In the next commit, all

+ features whose strings start with "tx-checksum-" will be added.

+ To make them take precedence over NET_DEV_FEAT_TX, it will be applied

+ only when each explicit feature is not applied.

+ ---

+  src/shared/ethtool-util.c | 55 ++++++++++++++++++++++++++++++++++++---

+  src/shared/ethtool-util.h |  4 ++-

+  2 files changed, 54 insertions(+), 5 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index 59b1bd86f085..e95ce1a20917 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -71,13 +71,14 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse P

+  

+  static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {

+          [NET_DEV_FEAT_RX]     = "rx-checksum",

+ -        [NET_DEV_FEAT_TX]     = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+          [NET_DEV_FEAT_GSO]    = "tx-generic-segmentation",

+          [NET_DEV_FEAT_GRO]    = "rx-gro",

+          [NET_DEV_FEAT_GRO_HW] = "rx-gro-hw",

+          [NET_DEV_FEAT_LRO]    = "rx-lro",

+          [NET_DEV_FEAT_TSO]    = "tx-tcp-segmentation",

+          [NET_DEV_FEAT_TSO6]   = "tx-tcp6-segmentation",

+ +

+ +        [NET_DEV_FEAT_TX]     = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+  };

+  

+  static const char* const ethtool_link_mode_bit_table[] = {

+ @@ -515,6 +516,43 @@ static int set_features_bit(

+                  const char *feature,

+                  int flag) {

+  

+ +        assert(strings);

+ +        assert(gfeatures);

+ +        assert(sfeatures);

+ +        assert(feature);

+ +

+ +        if (flag < 0)

+ +                return 0;

+ +

+ +        for (uint32_t i = 0; i < strings->len; i++) {

+ +                uint32_t block, mask;

+ +

+ +                if (!strneq((const char*) &strings->data[i * ETH_GSTRING_LEN], feature, ETH_GSTRING_LEN))

+ +                        continue;

+ +

+ +                block = i / 32;

+ +                mask = UINT32_C(1) << (i % 32);

+ +

+ +                if (!FLAGS_SET(gfeatures->features[block].available, mask) ||

+ +                    FLAGS_SET(gfeatures->features[block].never_changed, mask))

+ +                        return -EOPNOTSUPP;

+ +

+ +                sfeatures->features[block].valid |= mask;

+ +                SET_FLAG(sfeatures->features[block].requested, mask, flag);

+ +

+ +                return 0;

+ +        }

+ +

+ +        return -ENODATA;

+ +}

+ +

+ +static int set_features_multiple_bit(

+ +                const struct ethtool_gstrings *strings,

+ +                const struct ethtool_gfeatures *gfeatures,

+ +                struct ethtool_sfeatures *sfeatures,

+ +                const char *feature,

+ +                int flag) {

+ +

+          bool found = false;

+          int r = -ENODATA;

+  

+ @@ -529,8 +567,7 @@ static int set_features_bit(

+          for (uint32_t i = 0; i < strings->len; i++) {

+                  uint32_t block, mask;

+  

+ -                if (!strneq((const char*) &strings->data[i * ETH_GSTRING_LEN], feature, ETH_GSTRING_LEN) &&

+ -                    !(endswith(feature, "-") && startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature)))

+ +                if (!startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature))

+                          continue;

+  

+                  block = i / 32;

+ @@ -542,6 +579,10 @@ static int set_features_bit(

+                          continue;

+                  }

+  

+ +                /* The flags is explicitly set by set_features_bit() */

+ +                if (FLAGS_SET(sfeatures->features[block].valid, mask))

+ +                        continue;

+ +

+                  sfeatures->features[block].valid |= mask;

+                  SET_FLAG(sfeatures->features[block].requested, mask, flag);

+  

+ @@ -592,12 +633,18 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features

+          sfeatures->cmd = ETHTOOL_SFEATURES;

+          sfeatures->size = DIV_ROUND_UP(strings->len, 32U);

+  

+ -        for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) {

+ +        for (size_t i = 0; i < _NET_DEV_FEAT_SIMPLE_MAX; i++) {

+                  r = set_features_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]);

+                  if (r < 0)

+                          log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname);

+          }

+  

+ +        for (size_t i = _NET_DEV_FEAT_SIMPLE_MAX; i < _NET_DEV_FEAT_MAX; i++) {

+ +                r = set_features_multiple_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]);

+ +                if (r < 0)

+ +                        log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname);

+ +        }

+ +

+          ifr = (struct ifreq) {

+                  .ifr_data = (void*) sfeatures,

+          };

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index 6e180995055b..3f2252563304 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -20,13 +20,15 @@ typedef enum Duplex {

+  

+  typedef enum NetDevFeature {

+          NET_DEV_FEAT_RX,

+ -        NET_DEV_FEAT_TX,

+          NET_DEV_FEAT_GSO,

+          NET_DEV_FEAT_GRO,

+          NET_DEV_FEAT_GRO_HW,

+          NET_DEV_FEAT_LRO,

+          NET_DEV_FEAT_TSO,

+          NET_DEV_FEAT_TSO6,

+ +        _NET_DEV_FEAT_SIMPLE_MAX,

+ +

+ +        NET_DEV_FEAT_TX = _NET_DEV_FEAT_SIMPLE_MAX,

+          _NET_DEV_FEAT_MAX,

+          _NET_DEV_FEAT_INVALID = -EINVAL,

+  } NetDevFeature;

+ 

+ From 77bf5c31de1d01edd49ac6aa25cdbe7734a11a25 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Tue, 14 Sep 2021 22:12:42 +0900

+ Subject: [PATCH 5/5] ethtool-util: add more network device features

+ 

+ Then, we can easily add new settings to configure features in .link

+ file.

+ ---

+  src/shared/ethtool-util.c            | 73 ++++++++++++++++++++++++----

+  src/shared/ethtool-util.h            | 59 +++++++++++++++++++++-

+  src/udev/net/link-config-gperf.gperf |  4 +-

+  3 files changed, 123 insertions(+), 13 deletions(-)

+ 

+ diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c

+ index e95ce1a20917..00060abff40f 100644

+ --- a/src/shared/ethtool-util.c

+ +++ b/src/shared/ethtool-util.c

+ @@ -70,15 +70,70 @@ DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);

+  DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");

+  

+  static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {

+ -        [NET_DEV_FEAT_RX]     = "rx-checksum",

+ -        [NET_DEV_FEAT_GSO]    = "tx-generic-segmentation",

+ -        [NET_DEV_FEAT_GRO]    = "rx-gro",

+ -        [NET_DEV_FEAT_GRO_HW] = "rx-gro-hw",

+ -        [NET_DEV_FEAT_LRO]    = "rx-lro",

+ -        [NET_DEV_FEAT_TSO]    = "tx-tcp-segmentation",

+ -        [NET_DEV_FEAT_TSO6]   = "tx-tcp6-segmentation",

+ -

+ -        [NET_DEV_FEAT_TX]     = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+ +        [NET_DEV_FEAT_SG]                  = "tx-scatter-gather",

+ +        [NET_DEV_FEAT_IP_CSUM]             = "tx-checksum-ipv4",

+ +        [NET_DEV_FEAT_HW_CSUM]             = "tx-checksum-ip-generic",

+ +        [NET_DEV_FEAT_IPV6_CSUM]           = "tx-checksum-ipv6",

+ +        [NET_DEV_FEAT_HIGHDMA]             = "highdma",

+ +        [NET_DEV_FEAT_FRAGLIST]            = "tx-scatter-gather-fraglist",

+ +        [NET_DEV_FEAT_HW_VLAN_CTAG_TX]     = "tx-vlan-hw-insert",

+ +        [NET_DEV_FEAT_HW_VLAN_CTAG_RX]     = "rx-vlan-hw-parse",

+ +        [NET_DEV_FEAT_HW_VLAN_CTAG_FILTER] = "rx-vlan-filter",

+ +        [NET_DEV_FEAT_HW_VLAN_STAG_TX]     = "tx-vlan-stag-hw-insert",

+ +        [NET_DEV_FEAT_HW_VLAN_STAG_RX]     = "rx-vlan-stag-hw-parse",

+ +        [NET_DEV_FEAT_HW_VLAN_STAG_FILTER] = "rx-vlan-stag-filter",

+ +        [NET_DEV_FEAT_VLAN_CHALLENGED]     = "vlan-challenged",

+ +        [NET_DEV_FEAT_GSO]                 = "tx-generic-segmentation",

+ +        [NET_DEV_FEAT_LLTX]                = "tx-lockless",

+ +        [NET_DEV_FEAT_NETNS_LOCAL]         = "netns-local",

+ +        [NET_DEV_FEAT_GRO]                 = "rx-gro",

+ +        [NET_DEV_FEAT_GRO_HW]              = "rx-gro-hw",

+ +        [NET_DEV_FEAT_LRO]                 = "rx-lro",

+ +        [NET_DEV_FEAT_TSO]                 = "tx-tcp-segmentation",

+ +        [NET_DEV_FEAT_GSO_ROBUST]          = "tx-gso-robust",

+ +        [NET_DEV_FEAT_TSO_ECN]             = "tx-tcp-ecn-segmentation",

+ +        [NET_DEV_FEAT_TSO_MANGLEID]        = "tx-tcp-mangleid-segmentation",

+ +        [NET_DEV_FEAT_TSO6]                = "tx-tcp6-segmentation",

+ +        [NET_DEV_FEAT_FSO]                 = "tx-fcoe-segmentation",

+ +        [NET_DEV_FEAT_GSO_GRE]             = "tx-gre-segmentation",

+ +        [NET_DEV_FEAT_GSO_GRE_CSUM]        = "tx-gre-csum-segmentation",

+ +        [NET_DEV_FEAT_GSO_IPXIP4]          = "tx-ipxip4-segmentation",

+ +        [NET_DEV_FEAT_GSO_IPXIP6]          = "tx-ipxip6-segmentation",

+ +        [NET_DEV_FEAT_GSO_UDP_TUNNEL]      = "tx-udp_tnl-segmentation",

+ +        [NET_DEV_FEAT_GSO_UDP_TUNNEL_CSUM] = "tx-udp_tnl-csum-segmentation",

+ +        [NET_DEV_FEAT_GSO_PARTIAL]         = "tx-gso-partial",

+ +        [NET_DEV_FEAT_GSO_TUNNEL_REMCSUM]  = "tx-tunnel-remcsum-segmentation",

+ +        [NET_DEV_FEAT_GSO_SCTP]            = "tx-sctp-segmentation",

+ +        [NET_DEV_FEAT_GSO_ESP]             = "tx-esp-segmentation",

+ +        [NET_DEV_FEAT_GSO_UDP_L4]          = "tx-udp-segmentation",

+ +        [NET_DEV_FEAT_GSO_FRAGLIST]        = "tx-gso-list",

+ +        [NET_DEV_FEAT_FCOE_CRC]            = "tx-checksum-fcoe-crc",

+ +        [NET_DEV_FEAT_SCTP_CRC]            = "tx-checksum-sctp",

+ +        [NET_DEV_FEAT_FCOE_MTU]            = "fcoe-mtu",

+ +        [NET_DEV_FEAT_NTUPLE]              = "rx-ntuple-filter",

+ +        [NET_DEV_FEAT_RXHASH]              = "rx-hashing",

+ +        [NET_DEV_FEAT_RXCSUM]              = "rx-checksum",

+ +        [NET_DEV_FEAT_NOCACHE_COPY]        = "tx-nocache-copy",

+ +        [NET_DEV_FEAT_LOOPBACK]            = "loopback",

+ +        [NET_DEV_FEAT_RXFCS]               = "rx-fcs",

+ +        [NET_DEV_FEAT_RXALL]               = "rx-all",

+ +        [NET_DEV_FEAT_HW_L2FW_DOFFLOAD]    = "l2-fwd-offload",

+ +        [NET_DEV_FEAT_HW_TC]               = "hw-tc-offload",

+ +        [NET_DEV_FEAT_HW_ESP]              = "esp-hw-offload",

+ +        [NET_DEV_FEAT_HW_ESP_TX_CSUM]      = "esp-tx-csum-hw-offload",

+ +        [NET_DEV_FEAT_RX_UDP_TUNNEL_PORT]  = "rx-udp_tunnel-port-offload",

+ +        [NET_DEV_FEAT_HW_TLS_RECORD]       = "tls-hw-record",

+ +        [NET_DEV_FEAT_HW_TLS_TX]           = "tls-hw-tx-offload",

+ +        [NET_DEV_FEAT_HW_TLS_RX]           = "tls-hw-rx-offload",

+ +        [NET_DEV_FEAT_GRO_FRAGLIST]        = "rx-gro-list",

+ +        [NET_DEV_FEAT_HW_MACSEC]           = "macsec-hw-offload",

+ +        [NET_DEV_FEAT_GRO_UDP_FWD]         = "rx-udp-gro-forwarding",

+ +        [NET_DEV_FEAT_HW_HSR_TAG_INS]      = "hsr-tag-ins-offload",

+ +        [NET_DEV_FEAT_HW_HSR_TAG_RM]       = "hsr-tag-rm-offload",

+ +        [NET_DEV_FEAT_HW_HSR_FWD]          = "hsr-fwd-offload",

+ +        [NET_DEV_FEAT_HW_HSR_DUP]          = "hsr-dup-offload",

+ +

+ +        [NET_DEV_FEAT_TXCSUM]              = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */

+  };

+  

+  static const char* const ethtool_link_mode_bit_table[] = {

+ diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h

+ index 3f2252563304..cc0655893175 100644

+ --- a/src/shared/ethtool-util.h

+ +++ b/src/shared/ethtool-util.h

+ @@ -19,16 +19,71 @@ typedef enum Duplex {

+  } Duplex;

+  

+  typedef enum NetDevFeature {

+ -        NET_DEV_FEAT_RX,

+ +        NET_DEV_FEAT_SG,

+ +        NET_DEV_FEAT_IP_CSUM,

+ +        NET_DEV_FEAT_HW_CSUM,

+ +        NET_DEV_FEAT_IPV6_CSUM,

+ +        NET_DEV_FEAT_HIGHDMA,

+ +        NET_DEV_FEAT_FRAGLIST,

+ +        NET_DEV_FEAT_HW_VLAN_CTAG_TX,

+ +        NET_DEV_FEAT_HW_VLAN_CTAG_RX,

+ +        NET_DEV_FEAT_HW_VLAN_CTAG_FILTER,

+ +        NET_DEV_FEAT_HW_VLAN_STAG_TX,

+ +        NET_DEV_FEAT_HW_VLAN_STAG_RX,

+ +        NET_DEV_FEAT_HW_VLAN_STAG_FILTER,

+ +        NET_DEV_FEAT_VLAN_CHALLENGED,

+          NET_DEV_FEAT_GSO,

+ +        NET_DEV_FEAT_LLTX,

+ +        NET_DEV_FEAT_NETNS_LOCAL,

+          NET_DEV_FEAT_GRO,

+          NET_DEV_FEAT_GRO_HW,

+          NET_DEV_FEAT_LRO,

+          NET_DEV_FEAT_TSO,

+ +        NET_DEV_FEAT_GSO_ROBUST,

+ +        NET_DEV_FEAT_TSO_ECN,

+ +        NET_DEV_FEAT_TSO_MANGLEID,

+          NET_DEV_FEAT_TSO6,

+ +        NET_DEV_FEAT_FSO,

+ +        NET_DEV_FEAT_GSO_GRE,

+ +        NET_DEV_FEAT_GSO_GRE_CSUM,

+ +        NET_DEV_FEAT_GSO_IPXIP4,

+ +        NET_DEV_FEAT_GSO_IPXIP6,

+ +        NET_DEV_FEAT_GSO_UDP_TUNNEL,

+ +        NET_DEV_FEAT_GSO_UDP_TUNNEL_CSUM,

+ +        NET_DEV_FEAT_GSO_PARTIAL,

+ +        NET_DEV_FEAT_GSO_TUNNEL_REMCSUM,

+ +        NET_DEV_FEAT_GSO_SCTP,

+ +        NET_DEV_FEAT_GSO_ESP,

+ +        NET_DEV_FEAT_GSO_UDP_L4,

+ +        NET_DEV_FEAT_GSO_FRAGLIST,

+ +        NET_DEV_FEAT_FCOE_CRC,

+ +        NET_DEV_FEAT_SCTP_CRC,

+ +        NET_DEV_FEAT_FCOE_MTU,

+ +        NET_DEV_FEAT_NTUPLE,

+ +        NET_DEV_FEAT_RXHASH,

+ +        NET_DEV_FEAT_RXCSUM,

+ +        NET_DEV_FEAT_NOCACHE_COPY,

+ +        NET_DEV_FEAT_LOOPBACK,

+ +        NET_DEV_FEAT_RXFCS,

+ +        NET_DEV_FEAT_RXALL,

+ +        NET_DEV_FEAT_HW_L2FW_DOFFLOAD,

+ +        NET_DEV_FEAT_HW_TC,

+ +        NET_DEV_FEAT_HW_ESP,

+ +        NET_DEV_FEAT_HW_ESP_TX_CSUM,

+ +        NET_DEV_FEAT_RX_UDP_TUNNEL_PORT,

+ +        NET_DEV_FEAT_HW_TLS_RECORD,

+ +        NET_DEV_FEAT_HW_TLS_TX,

+ +        NET_DEV_FEAT_HW_TLS_RX,

+ +        NET_DEV_FEAT_GRO_FRAGLIST,

+ +        NET_DEV_FEAT_HW_MACSEC,

+ +        NET_DEV_FEAT_GRO_UDP_FWD,

+ +        NET_DEV_FEAT_HW_HSR_TAG_INS,

+ +        NET_DEV_FEAT_HW_HSR_TAG_RM,

+ +        NET_DEV_FEAT_HW_HSR_FWD,

+ +        NET_DEV_FEAT_HW_HSR_DUP,

+          _NET_DEV_FEAT_SIMPLE_MAX,

+  

+ -        NET_DEV_FEAT_TX = _NET_DEV_FEAT_SIMPLE_MAX,

+ +        NET_DEV_FEAT_TXCSUM = _NET_DEV_FEAT_SIMPLE_MAX,

+          _NET_DEV_FEAT_MAX,

+          _NET_DEV_FEAT_INVALID = -EINVAL,

+  } NetDevFeature;

+ diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf

+ index 44b46cb17c0b..e3cdaaee0509 100644

+ --- a/src/udev/net/link-config-gperf.gperf

+ +++ b/src/udev/net/link-config-gperf.gperf

+ @@ -50,8 +50,8 @@ Link.Duplex,                              config_parse_duplex,

+  Link.AutoNegotiation,                     config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+  Link.WakeOnLan,                           config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+  Link.Port,                                config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ -Link.ReceiveChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RX])

+ -Link.TransmitChecksumOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TX])

+ +Link.ReceiveChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM])

+ +Link.TransmitChecksumOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM])

+  Link.GenericSegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+  Link.TCPSegmentationOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+  Link.TCP6SegmentationOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

file added
+41
@@ -0,0 +1,41 @@ 

+ From 0fc51b569570e8bf5aecd5ee03a88eb668b7b385 Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Tue, 14 Sep 2021 16:33:10 -0700

+ Subject: [PATCH] fileio: start with 4k buffer for procfs

+ 

+ There's a very gradual increase of anonymous memory in systemd-journald that

+ blames to 2ac67221bb6270f0fbe7cbd0076653832cd49de2.

+ 

+ systemd-journald makes many calls to read /proc/PID/cmdline and

+ /proc/PID/status, both of which tend to be well under 4K. However the

+ combination of allocating 4M read buffers, then using `realloc()` to

+ shrink the buffer in `read_virtual_file()` appears to be creating

+ fragmentation in the heap (when combined with the other allocations

+ systemd-journald is doing).

+ 

+ To help mitigate this, try reading /proc with a 4K buffer as

+ `read_virtual_file()` did before 2ac67221bb6270f0fbe7cbd0076653832cd49de2.

+ If it isn't big enough then try again with the larger buffers.

+ ---

+  src/basic/fileio.c | 5 +++++

+  1 file changed, 5 insertions(+)

+ 

+ diff --git a/src/basic/fileio.c b/src/basic/fileio.c

+ index 99a44fdea2..466c6321c7 100644

+ --- a/src/basic/fileio.c

+ +++ b/src/basic/fileio.c

+ @@ -431,6 +431,11 @@ int read_virtual_file(const char *filename, size_t max_size, char **ret_contents

+                          }

+  

+                          n_retries--;

+ +                } else if (n_retries > 1) {

+ +                        /* Files in /proc are generally smaller than the page size so let's start with a page size

+ +                         * buffer from malloc and only use the max buffer on the final try. */

+ +                        size = MIN3(page_size() - 1, READ_VIRTUAL_BYTES_MAX, max_size);

+ +                        n_retries = 1;

+                  } else {

+                          size = MIN(READ_VIRTUAL_BYTES_MAX, max_size);

+                          n_retries = 0;

+ -- 

+ 2.31.1

+ 

file added
+240
@@ -0,0 +1,240 @@ 

+ From 88eca13f57194765d184ca227320df83f48020e2 Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Fri, 24 Sep 2021 01:19:00 -0700

+ Subject: [PATCH] link: connect 5 more properties to ethtool features

+ 

+ Sets up the follow properties and their corresponding ethtool feature:

+ - ReceiveVLANCTAGHardwareAcceleration == rx-vlan-hw-parse (or rxvlan)

+ - TransmitVLANCTAGHardwareAcceleration == tx-vlan-hw-insert (or txvlan)

+ - ReceiveVLANCTAGFilter == rx-vlan-filter

+ - TransmitVLANSTAGHardwareAcceleration == tx-vlan-stag-hw-insert

+ - NTupleFilter == rx-ntuple-filter (or ntuple)

+ ---

+  man/systemd.link.xml                       |  35 +++++

+  src/udev/net/link-config-gperf.gperf       | 153 +++++++++++----------

+  test/fuzz/fuzz-link-parser/directives.link |   5 +

+  3 files changed, 119 insertions(+), 74 deletions(-)

+ 

+ diff --git a/man/systemd.link.xml b/man/systemd.link.xml

+ index 638a1522cd38..c8d3c5137459 100644

+ --- a/man/systemd.link.xml

+ +++ b/man/systemd.link.xml

+ @@ -715,6 +715,41 @@

+            When unset, the kernel's default will be used.</para>

+          </listitem>

+        </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>ReceiveVLANCTAGHardwareAcceleration=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, receive VLAN CTAG hardware acceleration is enabled.

+ +          When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>TransmitVLANCTAGHardwareAcceleration=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, transmit VLAN CTAG hardware acceleration is enabled.

+ +          When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>ReceiveVLANCTAGFilter=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, receive filtering on VLAN CTAGs is enabled.

+ +          When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>TransmitVLANSTAGHardwareAcceleration=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, transmit VLAN STAG HW acceleration is enabled.

+ +          When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+ +      <varlistentry>

+ +        <term><varname>NTupleFilter=</varname></term>

+ +        <listitem>

+ +          <para>Takes a boolean. If set to true, receive N-tuple filters and actions are enabled.

+ +          When unset, the kernel's default will be used.</para>

+ +        </listitem>

+ +      </varlistentry>

+        <varlistentry>

+          <term><varname>RxChannels=</varname></term>

+          <term><varname>TxChannels=</varname></term>

+ diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf

+ index e3cdaaee0509..04c255ce514c 100644

+ --- a/src/udev/net/link-config-gperf.gperf

+ +++ b/src/udev/net/link-config-gperf.gperf

+ @@ -21,77 +21,82 @@ struct ConfigPerfItem;

+  %struct-type

+  %includes

+  %%

+ -Match.MACAddress,                         config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

+ -Match.PermanentMACAddress,                config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

+ -Match.OriginalName,                       config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

+ -Match.Path,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

+ -Match.Driver,                             config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

+ -Match.Type,                               config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

+ -Match.Property,                           config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

+ -Match.Host,                               config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

+ -Match.Virtualization,                     config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

+ -Match.KernelCommandLine,                  config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

+ -Match.KernelVersion,                      config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

+ -Match.Architecture,                       config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

+ -Link.Description,                         config_parse_string,                   0,                             offsetof(LinkConfig, description)

+ -Link.MACAddressPolicy,                    config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

+ -Link.MACAddress,                          config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

+ -Link.NamePolicy,                          config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

+ -Link.Name,                                config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

+ -Link.AlternativeName,                     config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

+ -Link.AlternativeNamesPolicy,              config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

+ -Link.Alias,                               config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

+ -Link.TransmitQueues,                      config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

+ -Link.ReceiveQueues,                       config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

+ -Link.TransmitQueueLength,                 config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

+ -Link.MTUBytes,                            config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

+ -Link.BitsPerSecond,                       config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

+ -Link.Duplex,                              config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

+ -Link.AutoNegotiation,                     config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+ -Link.WakeOnLan,                           config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+ -Link.Port,                                config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ -Link.ReceiveChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM])

+ -Link.TransmitChecksumOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM])

+ -Link.GenericSegmentationOffload,          config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+ -Link.TCPSegmentationOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+ -Link.TCP6SegmentationOffload,             config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+ -Link.UDPSegmentationOffload,              config_parse_warn_compat,              DISABLED_LEGACY,               0

+ -Link.GenericReceiveOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ -Link.GenericReceiveOffloadHardware,       config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW])

+ -Link.LargeReceiveOffload,                 config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ -Link.RxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ -Link.TxChannels,                          config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ -Link.OtherChannels,                       config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ -Link.CombinedChannels,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+ -Link.Advertise,                           config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ -Link.RxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ -Link.RxMiniBufferSize,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ -Link.RxJumboBufferSize,                   config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ -Link.TxBufferSize,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+ -Link.RxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+ -Link.TxFlowControl,                       config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+ -Link.AutoNegotiationFlowControl,          config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ -Link.GenericSegmentOffloadMaxBytes,       config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

+ -Link.GenericSegmentOffloadMaxSegments,    config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ -Link.RxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs)

+ -Link.RxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames)

+ -Link.RxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq)

+ -Link.RxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq)

+ -Link.TxCoalesceSec,                       config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs)

+ -Link.TxMaxCoalescedFrames,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames)

+ -Link.TxCoalesceIrqSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq)

+ -Link.TxMaxCoalescedIrqFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq)

+ -Link.StatisticsBlockCoalesceSec,          config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs)

+ -Link.UseAdaptiveRxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce)

+ -Link.UseAdaptiveTxCoalesce,               config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce)

+ -Link.CoalescePacketRateLow,               config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_low)

+ -Link.RxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low)

+ -Link.RxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low)

+ -Link.TxCoalesceLowSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low)

+ -Link.TxMaxCoalescedLowFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low)

+ -Link.CoalescePacketRateHigh,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_high)

+ -Link.RxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high)

+ -Link.RxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high)

+ -Link.TxCoalesceHighSec,                   config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)

+ -Link.TxMaxCoalescedHighFrames,            config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)

+ -Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rate_sample_interval)

+ +Match.MACAddress,                          config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.mac)

+ +Match.PermanentMACAddress,                 config_parse_hwaddrs,                  0,                             offsetof(LinkConfig, match.permanent_mac)

+ +Match.OriginalName,                        config_parse_match_ifnames,            0,                             offsetof(LinkConfig, match.ifname)

+ +Match.Path,                                config_parse_match_strv,               0,                             offsetof(LinkConfig, match.path)

+ +Match.Driver,                              config_parse_match_strv,               0,                             offsetof(LinkConfig, match.driver)

+ +Match.Type,                                config_parse_match_strv,               0,                             offsetof(LinkConfig, match.iftype)

+ +Match.Property,                            config_parse_match_property,           0,                             offsetof(LinkConfig, match.property)

+ +Match.Host,                                config_parse_net_condition,            CONDITION_HOST,                offsetof(LinkConfig, conditions)

+ +Match.Virtualization,                      config_parse_net_condition,            CONDITION_VIRTUALIZATION,      offsetof(LinkConfig, conditions)

+ +Match.KernelCommandLine,                   config_parse_net_condition,            CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions)

+ +Match.KernelVersion,                       config_parse_net_condition,            CONDITION_KERNEL_VERSION,      offsetof(LinkConfig, conditions)

+ +Match.Architecture,                        config_parse_net_condition,            CONDITION_ARCHITECTURE,        offsetof(LinkConfig, conditions)

+ +Link.Description,                          config_parse_string,                   0,                             offsetof(LinkConfig, description)

+ +Link.MACAddressPolicy,                     config_parse_mac_address_policy,       0,                             offsetof(LinkConfig, mac_address_policy)

+ +Link.MACAddress,                           config_parse_hwaddr,                   0,                             offsetof(LinkConfig, mac)

+ +Link.NamePolicy,                           config_parse_name_policy,              0,                             offsetof(LinkConfig, name_policy)

+ +Link.Name,                                 config_parse_ifname,                   0,                             offsetof(LinkConfig, name)

+ +Link.AlternativeName,                      config_parse_ifnames,                  IFNAME_VALID_ALTERNATIVE,      offsetof(LinkConfig, alternative_names)

+ +Link.AlternativeNamesPolicy,               config_parse_alternative_names_policy, 0,                             offsetof(LinkConfig, alternative_names_policy)

+ +Link.Alias,                                config_parse_ifalias,                  0,                             offsetof(LinkConfig, alias)

+ +Link.TransmitQueues,                       config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, txqueues)

+ +Link.ReceiveQueues,                        config_parse_rx_tx_queues,             0,                             offsetof(LinkConfig, rxqueues)

+ +Link.TransmitQueueLength,                  config_parse_txqueuelen,               0,                             offsetof(LinkConfig, txqueuelen)

+ +Link.MTUBytes,                             config_parse_mtu,                      AF_UNSPEC,                     offsetof(LinkConfig, mtu)

+ +Link.BitsPerSecond,                        config_parse_si_uint64,                0,                             offsetof(LinkConfig, speed)

+ +Link.Duplex,                               config_parse_duplex,                   0,                             offsetof(LinkConfig, duplex)

+ +Link.AutoNegotiation,                      config_parse_tristate,                 0,                             offsetof(LinkConfig, autonegotiation)

+ +Link.WakeOnLan,                            config_parse_wol,                      0,                             offsetof(LinkConfig, wol)

+ +Link.Port,                                 config_parse_port,                     0,                             offsetof(LinkConfig, port)

+ +Link.ReceiveChecksumOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM])

+ +Link.TransmitChecksumOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM])

+ +Link.GenericSegmentationOffload,           config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GSO])

+ +Link.TCPSegmentationOffload,               config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO])

+ +Link.TCP6SegmentationOffload,              config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6])

+ +Link.UDPSegmentationOffload,               config_parse_warn_compat,              DISABLED_LEGACY,               0

+ +Link.GenericReceiveOffload,                config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])

+ +Link.GenericReceiveOffloadHardware,        config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW])

+ +Link.LargeReceiveOffload,                  config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])

+ +Link.ReceiveVLANCTAGHardwareAcceleration,  config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_RX])

+ +Link.TransmitVLANCTAGHardwareAcceleration, config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_TX])

+ +Link.ReceiveVLANCTAGFilter,                config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_FILTER])

+ +Link.TransmitVLANSTAGHardwareAcceleration, config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_STAG_TX])

+ +Link.NTupleFilter,                         config_parse_tristate,                 0,                             offsetof(LinkConfig, features[NET_DEV_FEAT_NTUPLE])

+ +Link.RxChannels,                           config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.rx)

+ +Link.TxChannels,                           config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.tx)

+ +Link.OtherChannels,                        config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.other)

+ +Link.CombinedChannels,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, channels.combined)

+ +Link.Advertise,                            config_parse_advertise,                0,                             offsetof(LinkConfig, advertise)

+ +Link.RxBufferSize,                         config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx)

+ +Link.RxMiniBufferSize,                     config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_mini)

+ +Link.RxJumboBufferSize,                    config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.rx_jumbo)

+ +Link.TxBufferSize,                         config_parse_ring_buffer_or_channel,   0,                             offsetof(LinkConfig, ring.tx)

+ +Link.RxFlowControl,                        config_parse_tristate,                 0,                             offsetof(LinkConfig, rx_flow_control)

+ +Link.TxFlowControl,                        config_parse_tristate,                 0,                             offsetof(LinkConfig, tx_flow_control)

+ +Link.AutoNegotiationFlowControl,           config_parse_tristate,                 0,                             offsetof(LinkConfig, autoneg_flow_control)

+ +Link.GenericSegmentOffloadMaxBytes,        config_parse_iec_size,                 0,                             offsetof(LinkConfig, gso_max_size)

+ +Link.GenericSegmentOffloadMaxSegments,     config_parse_uint32,                   0,                             offsetof(LinkConfig, gso_max_segments)

+ +Link.RxCoalesceSec,                        config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs)

+ +Link.RxMaxCoalescedFrames,                 config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames)

+ +Link.RxCoalesceIrqSec,                     config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq)

+ +Link.RxMaxCoalescedIrqFrames,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq)

+ +Link.TxCoalesceSec,                        config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs)

+ +Link.TxMaxCoalescedFrames,                 config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames)

+ +Link.TxCoalesceIrqSec,                     config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq)

+ +Link.TxMaxCoalescedIrqFrames,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq)

+ +Link.StatisticsBlockCoalesceSec,           config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs)

+ +Link.UseAdaptiveRxCoalesce,                config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce)

+ +Link.UseAdaptiveTxCoalesce,                config_parse_tristate,                 0,                             offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce)

+ +Link.CoalescePacketRateLow,                config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_low)

+ +Link.RxCoalesceLowSec,                     config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low)

+ +Link.RxMaxCoalescedLowFrames,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low)

+ +Link.TxCoalesceLowSec,                     config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low)

+ +Link.TxMaxCoalescedLowFrames,              config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low)

+ +Link.CoalescePacketRateHigh,               config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.pkt_rate_high)

+ +Link.RxCoalesceHighSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high)

+ +Link.RxMaxCoalescedHighFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high)

+ +Link.TxCoalesceHighSec,                    config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high)

+ +Link.TxMaxCoalescedHighFrames,             config_parse_coalesce_u32,             0,                             offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high)

+ +Link.CoalescePacketRateSampleIntervalSec,  config_parse_coalesce_sec,             0,                             offsetof(LinkConfig, coalesce.rate_sample_interval)

+ diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link

+ index b5cffb1a271f..8be2434665a7 100644

+ --- a/test/fuzz/fuzz-link-parser/directives.link

+ +++ b/test/fuzz/fuzz-link-parser/directives.link

+ @@ -38,6 +38,11 @@ UDPSegmentationOffload=

+  GenericReceiveOffload=

+  GenericReceiveOffloadHardware=

+  LargeReceiveOffload=

+ +ReceiveVLANCTAGHardwareAcceleration=

+ +TransmitVLANCTAGHardwareAcceleration=

+ +ReceiveVLANCTAGFilter=

+ +TransmitVLANSTAGHardwareAcceleration=

+ +NTupleFilter=

+  RxChannels=

+  TxChannels=

+  OtherChannels=

file added
+26
@@ -0,0 +1,26 @@ 

+ From 84e1818ce1dc9f5f7eb7b4d4bc87124d82c5080f Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Tue, 28 Sep 2021 23:52:39 -0700

+ Subject: [PATCH] basic/unit-file: don't filter out names starting with dot

+ 

+ Fixes #20859

+ ---

+  src/basic/unit-file.c | 2 +-

+  1 file changed, 1 insertion(+), 1 deletion(-)

+ 

+ diff --git a/src/basic/unit-file.c b/src/basic/unit-file.c

+ index 884a0674a9..0d58b1c4fe 100644

+ --- a/src/basic/unit-file.c

+ +++ b/src/basic/unit-file.c

+ @@ -284,7 +284,7 @@ int unit_file_build_name_map(

+                          continue;

+                  }

+  

+ -                FOREACH_DIRENT(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {

+ +                FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) {

+                          char *filename;

+                          _cleanup_free_ char *_filename_free = NULL, *simplified = NULL;

+                          const char *suffix, *dst = NULL;

+ -- 

+ 2.31.1

+ 

file added
+126
@@ -0,0 +1,126 @@ 

+ From a58dea6130fdcccd8cdf50633c939b45e2b32189 Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Mon, 11 Oct 2021 00:25:20 -0700

+ Subject: [PATCH] core: serialize device cgroup bpf progs across

+  daemon-reload/reexec

+ 

+ Follows what was done in b57d75232615f98aefcf41cb145ec2ea3262857d and

+ adds a test that verifies the device BPF program is not detached during

+ reload/reexec.

+ ---

+  src/core/unit-serialize.c                     |  4 ++++

+  test/TEST-66-DEVICE-ISOLATION/Makefile        |  1 +

+  test/TEST-66-DEVICE-ISOLATION/test.sh         | 10 ++++++++

+  .../testsuite-66-deviceisolation.service      |  9 ++++++++

+  test/units/testsuite-66.service               |  7 ++++++

+  test/units/testsuite-66.sh                    | 23 +++++++++++++++++++

+  6 files changed, 54 insertions(+)

+  create mode 120000 test/TEST-66-DEVICE-ISOLATION/Makefile

+  create mode 100755 test/TEST-66-DEVICE-ISOLATION/test.sh

+  create mode 100644 test/units/testsuite-66-deviceisolation.service

+  create mode 100644 test/units/testsuite-66.service

+  create mode 100755 test/units/testsuite-66.sh

+ 

+ diff --git a/src/core/unit-serialize.c b/src/core/unit-serialize.c

+ index 9e1664ff53af..3458d7017bd5 100644

+ --- a/src/core/unit-serialize.c

+ +++ b/src/core/unit-serialize.c

+ @@ -171,6 +171,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool switching_root) {

+  

+          (void) bpf_program_serialize_attachment(f, fds, "ip-bpf-ingress-installed", u->ip_bpf_ingress_installed);

+          (void) bpf_program_serialize_attachment(f, fds, "ip-bpf-egress-installed", u->ip_bpf_egress_installed);

+ +        (void) bpf_program_serialize_attachment(f, fds, "bpf-device-control-installed", u->bpf_device_control_installed);

+          (void) bpf_program_serialize_attachment_set(f, fds, "ip-bpf-custom-ingress-installed", u->ip_bpf_custom_ingress_installed);

+          (void) bpf_program_serialize_attachment_set(f, fds, "ip-bpf-custom-egress-installed", u->ip_bpf_custom_egress_installed);

+  

+ @@ -408,6 +409,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) {

+                  } else if (streq(l, "ip-bpf-egress-installed")) {

+                           (void) bpf_program_deserialize_attachment(v, fds, &u->ip_bpf_egress_installed);

+                           continue;

+ +                } else if (streq(l, "bpf-device-control-installed")) {

+ +                         (void) bpf_program_deserialize_attachment(v, fds, &u->bpf_device_control_installed);

+ +                         continue;

+  

+                  } else if (streq(l, "ip-bpf-custom-ingress-installed")) {

+                           (void) bpf_program_deserialize_attachment_set(v, fds, &u->ip_bpf_custom_ingress_installed);

+ diff --git a/test/TEST-66-DEVICE-ISOLATION/Makefile b/test/TEST-66-DEVICE-ISOLATION/Makefile

+ new file mode 120000

+ index 000000000000..e9f93b1104cd

+ --- /dev/null

+ +++ b/test/TEST-66-DEVICE-ISOLATION/Makefile

+ @@ -0,0 +1 @@

+ +../TEST-01-BASIC/Makefile

+ \ No newline at end of file

+ diff --git a/test/TEST-66-DEVICE-ISOLATION/test.sh b/test/TEST-66-DEVICE-ISOLATION/test.sh

+ new file mode 100755

+ index 000000000000..534e43e493e6

+ --- /dev/null

+ +++ b/test/TEST-66-DEVICE-ISOLATION/test.sh

+ @@ -0,0 +1,10 @@

+ +#!/usr/bin/env bash

+ +set -e

+ +

+ +TEST_DESCRIPTION="test device isolation"

+ +TEST_NO_NSPAWN=1

+ +

+ +# shellcheck source=test/test-functions

+ +. "${TEST_BASE_DIR:?}/test-functions"

+ +

+ +do_test "$@"

+ diff --git a/test/units/testsuite-66-deviceisolation.service b/test/units/testsuite-66-deviceisolation.service

+ new file mode 100644

+ index 000000000000..0022a9a45724

+ --- /dev/null

+ +++ b/test/units/testsuite-66-deviceisolation.service

+ @@ -0,0 +1,9 @@

+ +[Unit]

+ +Description=Service that uses device isolation

+ +

+ +[Service]

+ +DevicePolicy=strict

+ +DeviceAllow=/dev/null r

+ +StandardOutput=file:/testsuite66serviceresults

+ +ExecStartPre=rm -f /testsuite66serviceresults

+ +ExecStart=/bin/bash -c "while true; do sleep 0.01 && echo meow > /dev/null && echo thisshouldnotbehere; done"

+ diff --git a/test/units/testsuite-66.service b/test/units/testsuite-66.service

+ new file mode 100644

+ index 000000000000..a97974a4262d

+ --- /dev/null

+ +++ b/test/units/testsuite-66.service

+ @@ -0,0 +1,7 @@

+ +[Unit]

+ +Description=TESTSUITE-66-DEVICEISOLATION

+ +

+ +[Service]

+ +ExecStartPre=rm -f /failed /testok

+ +ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh

+ +Type=oneshot

+ diff --git a/test/units/testsuite-66.sh b/test/units/testsuite-66.sh

+ new file mode 100755

+ index 000000000000..870dca42e169

+ --- /dev/null

+ +++ b/test/units/testsuite-66.sh

+ @@ -0,0 +1,23 @@

+ +#!/usr/bin/env bash

+ +set -eux

+ +set -o pipefail

+ +

+ +systemd-analyze log-level debug

+ +systemd-analyze log-target console

+ +

+ +systemctl start testsuite-66-deviceisolation.service

+ +

+ +grep -q "Operation not permitted" /testsuite66serviceresults

+ +

+ +systemctl daemon-reload

+ +systemctl daemon-reexec

+ +

+ +systemctl stop testsuite-66-deviceisolation.service

+ +

+ +grep -q "thisshouldnotbehere" /testsuite66serviceresults && exit 42

+ +

+ +systemd-analyze log-level info

+ +

+ +echo OK >/testok

+ +

+ +exit 0

file added
+172
@@ -0,0 +1,172 @@ 

+ From fbdc87679cc4f3c9fc3653636e94be20f06d18e4 Mon Sep 17 00:00:00 2001

+ From: Anita Zhang <the.anitazha@gmail.com>

+ Date: Tue, 9 Nov 2021 15:26:28 -0800

+ Subject: [PATCH] core: replace slice dependencies as they get added

+ 

+ Defines a "UNIT_DEPENDENCY_SLICE_PROPERTY" UnitDependencyMask type that

+ is used when adding slices to the dependencies hashmap. This type is

+ used to remove slice dependencies when they get overridden by new ones.

+ 

+ Fixes #20182

+ ---

+  src/core/dbus-unit.c      |  2 +-

+  src/core/load-fragment.c  |  2 +-

+  src/core/unit-serialize.c |  1 +

+  src/core/unit.c           | 10 +++++++---

+  src/core/unit.h           |  7 +++++--

+  src/test/test-engine.c    | 31 ++++++++++++++++++++++++++++++-

+  6 files changed, 45 insertions(+), 8 deletions(-)

+ 

+ diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c

+ index fe320f1b05a8..d4ec789a7c11 100644

+ --- a/src/core/dbus-unit.c

+ +++ b/src/core/dbus-unit.c

+ @@ -2273,7 +2273,7 @@ static int bus_unit_set_transient_property(

+                          return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit name '%s' is not a slice", s);

+  

+                  if (!UNIT_WRITE_FLAGS_NOOP(flags)) {

+ -                        r = unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);

+ +                        r = unit_set_slice(u, slice);

+                          if (r < 0)

+                                  return r;

+  

+ diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c

+ index 62cadaf2286f..830048ae1915 100644

+ --- a/src/core/load-fragment.c

+ +++ b/src/core/load-fragment.c

+ @@ -3792,7 +3792,7 @@ int config_parse_unit_slice(

+                  return 0;

+          }

+  

+ -        r = unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);

+ +        r = unit_set_slice(u, slice);

+          if (r < 0) {

+                  log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to assign slice %s to unit %s, ignoring: %m", slice->id, u->id);

+                  return 0;

+ diff --git a/src/core/unit-serialize.c b/src/core/unit-serialize.c

+ index 3458d7017bd5..7d2e6bc130de 100644

+ --- a/src/core/unit-serialize.c

+ +++ b/src/core/unit-serialize.c

+ @@ -593,6 +593,7 @@ static void print_unit_dependency_mask(FILE *f, const char *kind, UnitDependency

+                  { UNIT_DEPENDENCY_MOUNTINFO_IMPLICIT, "mountinfo-implicit" },

+                  { UNIT_DEPENDENCY_MOUNTINFO_DEFAULT,  "mountinfo-default"  },

+                  { UNIT_DEPENDENCY_PROC_SWAP,          "proc-swap"          },

+ +                { UNIT_DEPENDENCY_SLICE_PROPERTY,     "slice-property"     },

+          };

+  

+          assert(f);

+ diff --git a/src/core/unit.c b/src/core/unit.c

+ index 4c55827a6511..a3bca43566e0 100644

+ --- a/src/core/unit.c

+ +++ b/src/core/unit.c

+ @@ -3284,7 +3284,7 @@ int unit_set_invocation_id(Unit *u, sd_id128_t id) {

+          return r;

+  }

+  

+ -int unit_set_slice(Unit *u, Unit *slice, UnitDependencyMask mask) {

+ +int unit_set_slice(Unit *u, Unit *slice) {

+          int r;

+  

+          assert(u);

+ @@ -3317,7 +3317,11 @@ int unit_set_slice(Unit *u, Unit *slice, UnitDependencyMask mask) {

+          if (UNIT_GET_SLICE(u) && u->cgroup_realized)

+                  return -EBUSY;

+  

+ -        r = unit_add_dependency(u, UNIT_IN_SLICE, slice, true, mask);

+ +        /* Remove any slices assigned prior; we should only have one UNIT_IN_SLICE dependency */

+ +        if (UNIT_GET_SLICE(u))

+ +                unit_remove_dependencies(u, UNIT_DEPENDENCY_SLICE_PROPERTY);

+ +

+ +        r = unit_add_dependency(u, UNIT_IN_SLICE, slice, true, UNIT_DEPENDENCY_SLICE_PROPERTY);

+          if (r < 0)

+                  return r;

+  

+ @@ -3373,7 +3377,7 @@ int unit_set_default_slice(Unit *u) {

+          if (r < 0)

+                  return r;

+  

+ -        return unit_set_slice(u, slice, UNIT_DEPENDENCY_FILE);

+ +        return unit_set_slice(u, slice);

+  }

+  

+  const char *unit_slice_name(Unit *u) {

+ diff --git a/src/core/unit.h b/src/core/unit.h

+ index 0dd6a9591d96..ba12fe4ac1ef 100644

+ --- a/src/core/unit.h

+ +++ b/src/core/unit.h

+ @@ -89,7 +89,10 @@ typedef enum UnitDependencyMask {

+          /* A dependency created because of data read from /proc/swaps and no other configuration source */

+          UNIT_DEPENDENCY_PROC_SWAP          = 1 << 7,

+  

+ -        _UNIT_DEPENDENCY_MASK_FULL         = (1 << 8) - 1,

+ +        /* A dependency for units in slices assigned by directly setting Slice= */

+ +        UNIT_DEPENDENCY_SLICE_PROPERTY     = 1 << 8,

+ +

+ +        _UNIT_DEPENDENCY_MASK_FULL         = (1 << 9) - 1,

+  } UnitDependencyMask;

+  

+  /* The Unit's dependencies[] hashmaps use this structure as value. It has the same size as a void pointer, and thus can

+ @@ -782,7 +785,7 @@ Unit *unit_follow_merge(Unit *u) _pure_;

+  int unit_load_fragment_and_dropin(Unit *u, bool fragment_required);

+  int unit_load(Unit *unit);

+  

+ -int unit_set_slice(Unit *u, Unit *slice, UnitDependencyMask mask);

+ +int unit_set_slice(Unit *u, Unit *slice);

+  int unit_set_default_slice(Unit *u);

+  

+  const char *unit_description(Unit *u) _pure_;

+ diff --git a/src/test/test-engine.c b/src/test/test-engine.c

+ index 880af36fb523..673c66561240 100644

+ --- a/src/test/test-engine.c

+ +++ b/src/test/test-engine.c

+ @@ -8,6 +8,7 @@

+  #include "manager-dump.h"

+  #include "rm-rf.h"

+  #include "service.h"

+ +#include "slice.h"

+  #include "special.h"

+  #include "strv.h"

+  #include "tests.h"

+ @@ -75,7 +76,8 @@ int main(int argc, char *argv[]) {

+          _cleanup_(sd_bus_error_free) sd_bus_error err = SD_BUS_ERROR_NULL;

+          _cleanup_(manager_freep) Manager *m = NULL;

+          Unit *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL, *g = NULL,

+ -                *h = NULL, *i = NULL, *a_conj = NULL, *unit_with_multiple_dashes = NULL, *stub = NULL;

+ +                *h = NULL, *i = NULL, *a_conj = NULL, *unit_with_multiple_dashes = NULL, *stub = NULL,

+ +                *tomato = NULL, *sauce = NULL, *fruit = NULL, *zupa = NULL;

+          Job *j;

+          int r;

+  

+ @@ -260,5 +262,32 @@ int main(int argc, char *argv[]) {

+  

+          verify_dependency_atoms();

+  

+ +        /* Test adding multiple Slice= dependencies; only the last should remain */

+ +        assert_se(unit_new_for_name(m, sizeof(Service), "tomato.service", &tomato) >= 0);

+ +        assert_se(unit_new_for_name(m, sizeof(Slice), "sauce.slice", &sauce) >= 0);

+ +        assert_se(unit_new_for_name(m, sizeof(Slice), "fruit.slice", &fruit) >= 0);

+ +        assert_se(unit_new_for_name(m, sizeof(Slice), "zupa.slice", &zupa) >= 0);

+ +

+ +        unit_set_slice(tomato, sauce);

+ +        unit_set_slice(tomato, fruit);

+ +        unit_set_slice(tomato, zupa);

+ +

+ +        assert_se(UNIT_GET_SLICE(tomato) == zupa);

+ +        assert_se(!unit_has_dependency(tomato, UNIT_ATOM_IN_SLICE, sauce));

+ +        assert_se(!unit_has_dependency(tomato, UNIT_ATOM_IN_SLICE, fruit));

+ +        assert_se(unit_has_dependency(tomato, UNIT_ATOM_IN_SLICE, zupa));

+ +

+ +        assert_se(!unit_has_dependency(tomato, UNIT_ATOM_REFERENCES, sauce));

+ +        assert_se(!unit_has_dependency(tomato, UNIT_ATOM_REFERENCES, fruit));

+ +        assert_se(unit_has_dependency(tomato, UNIT_ATOM_REFERENCES, zupa));

+ +

+ +        assert_se(!unit_has_dependency(sauce, UNIT_ATOM_SLICE_OF, tomato));

+ +        assert_se(!unit_has_dependency(fruit, UNIT_ATOM_SLICE_OF, tomato));

+ +        assert_se(unit_has_dependency(zupa, UNIT_ATOM_SLICE_OF, tomato));

+ +

+ +        assert_se(!unit_has_dependency(sauce, UNIT_ATOM_REFERENCED_BY, tomato));

+ +        assert_se(!unit_has_dependency(fruit, UNIT_ATOM_REFERENCED_BY, tomato));

+ +        assert_se(unit_has_dependency(zupa, UNIT_ATOM_REFERENCED_BY, tomato));

+ +

+          return 0;

+  }

@@ -0,0 +1,116 @@ 

+ From 1035e36675e10522824476c9084ff1001039c054 Mon Sep 17 00:00:00 2001

+ From: Yu Watanabe <watanabe.yu+github@gmail.com>

+ Date: Fri, 1 Oct 2021 09:22:18 +0900

+ Subject: [PATCH] network: drop and warn duplicated Address= settings

+ 

+ Fixes #20891.

+ ---

+  src/network/networkd-address.c | 43 +++++++++++++++++++++++++++++++---

+  src/network/networkd-address.h |  2 +-

+  src/network/networkd-network.c |  6 ++++-

+  3 files changed, 46 insertions(+), 5 deletions(-)

+ 

+ diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c

+ index 7b221516d7..e1bc6aa474 100644

+ --- a/src/network/networkd-address.c

+ +++ b/src/network/networkd-address.c

+ @@ -304,6 +304,12 @@ bool address_equal(const Address *a1, const Address *a2) {

+          return address_compare_func(a1, a2) == 0;

+  }

+  

+ +DEFINE_PRIVATE_HASH_OPS(

+ +        address_hash_ops_new,

+ +        Address,

+ +        address_hash_func,

+ +        address_compare_func);

+ +

+  int address_dup(const Address *src, Address **ret) {

+          _cleanup_(address_freep) Address *dest = NULL;

+          int r;

+ @@ -1988,12 +1994,43 @@ static int address_section_verify(Address *address) {

+          return 0;

+  }

+  

+ -void network_drop_invalid_addresses(Network *network) {

+ +int network_drop_invalid_addresses(Network *network) {

+ +        _cleanup_set_free_ Set *addresses = NULL;

+          Address *address;

+ +        int r;

+  

+          assert(network);

+  

+ -        ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)

+ -                if (address_section_verify(address) < 0)

+ +        ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section) {

+ +                Address *dup;

+ +

+ +                if (address_section_verify(address) < 0) {

+ +                        /* Drop invalid [Address] sections or Address= settings in [Network].

+ +                         * Note that address_free() will drop the address from addresses_by_section. */

+                          address_free(address);

+ +                        continue;

+ +                }

+ +

+ +                /* Always use the setting specified later. So, remove the previously assigned setting. */

+ +                dup = set_remove(addresses, address);

+ +                if (dup) {

+ +                        _cleanup_free_ char *buf = NULL;

+ +

+ +                        (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buf);

+ +                        log_warning("%s: Duplicated address %s is specified at line %u and %u, "

+ +                                    "dropping the address setting specified at line %u.",

+ +                                    dup->section->filename, strna(buf), address->section->line,

+ +                                    dup->section->line, dup->section->line);

+ +                        /* address_free() will drop the address from addresses_by_section. */

+ +                        address_free(dup);

+ +                }

+ +

+ +                /* Do not use address_hash_ops_free here. Otherwise, all address settings will be freed. */

+ +                r = set_ensure_put(&addresses, &address_hash_ops_new, address);

+ +                if (r < 0)

+ +                        return log_oom();

+ +                assert(r > 0);

+ +        }

+ +

+ +        return 0;

+  }

+ diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h

+ index ff3d46abdd..55d22ad221 100644

+ --- a/src/network/networkd-address.h

+ +++ b/src/network/networkd-address.h

+ @@ -85,7 +85,7 @@ int request_process_address(Request *req);

+  

+  int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);

+  

+ -void network_drop_invalid_addresses(Network *network);

+ +int network_drop_invalid_addresses(Network *network);

+  

+  void address_hash_func(const Address *a, struct siphash *state);

+  int address_compare_func(const Address *a1, const Address *a2);

+ diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c

+ index 2a864a38b1..920f7851ba 100644

+ --- a/src/network/networkd-network.c

+ +++ b/src/network/networkd-network.c

+ @@ -119,6 +119,8 @@ static int network_resolve_stacked_netdevs(Network *network) {

+  }

+  

+  int network_verify(Network *network) {

+ +        int r;

+ +

+          assert(network);

+          assert(network->filename);

+  

+ @@ -252,7 +254,9 @@ int network_verify(Network *network) {

+                  network->ipv6_proxy_ndp_addresses = set_free_free(network->ipv6_proxy_ndp_addresses);

+          }

+  

+ -        network_drop_invalid_addresses(network);

+ +        r = network_drop_invalid_addresses(network);

+ +        if (r < 0)

+ +                return r;

+          network_drop_invalid_routes(network);

+          network_drop_invalid_nexthops(network);

+          network_drop_invalid_bridge_fdb_entries(network);

+ -- 

+ 2.31.1

+ 

@@ -1,13 +0,0 @@ 

- diff --git a/rules.d/60-persistent-storage.rules b/rules.d/60-persistent-storage.rules

- index 1d8880e..46ea568 100644

- --- a/rules.d/60-persistent-storage.rules

- +++ b/rules.d/60-persistent-storage.rules

- @@ -7,7 +7,7 @@ ACTION=="remove", GOTO="persistent_storage_end"

-  ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="persistent_storage_end"

-  

-  SUBSYSTEM!="block", GOTO="persistent_storage_end"

- -KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end"

- +KERNEL!="loop*|mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|fio*|nvme*|sd*|sr*|vd*|xvd*|bcache*|cciss*|dasd*|ubd*|ubi*|scm*|pmem*|nbd*|zd*", GOTO="persistent_storage_end"

-  

-  # ignore partitions that span the entire disk

-  TEST=="whole_disk", GOTO="persistent_storage_end"

@@ -0,0 +1,16 @@ 

+ TARGETS ?= systemd_hs

+ SHARE ?= /usr/share

+ MODULES ?= ${TARGETS:=.pp.bz2}

+ 

+ all: ${TARGETS:=.pp.bz2}

+ 

+ %.pp.bz2: %.pp

+ 	@echo Compressing $^ -\ $@

+ 	bzip2 -9 $^

+ 

+ %.pp: %.te

+ 	make -f ${SHARE}/selinux/devel/Makefile $@

+ 

+ clean:

+ 	rm -f *~ *.tc *.pp *.pp.bz2

+ 	rm -rf tmp

@@ -0,0 +1,14 @@ 

+ == Building systemd rpms for local development using rpmbuild --build-in-place ==

+ 

+ This approach is based on https://github.com/filbranden/git-rpmbuild

+ and filbranden's talk during ASG2019 [https://cfp.all-systems-go.io/ASG2019/talk/JM7GDN/].

+ 

+ ```

+ git clone https://github.com/systemd/systemd

+ fedpkg clone systemd fedora-systemd

+ cd systemd

+ rpmbuild -bb --build-in-place --noprep --define "_sourcedir $PWD/../fedora-systemd" --define "_rpmdir $PWD/rpms" --with inplace ../systemd.spec

+ sudo dnf upgrade --setopt install_weak_deps=False rpms/*/*.rpm

+ ```

+ 

+ `--without lto` and `--without tests` may be useful to speed up the build.

@@ -0,0 +1,129 @@ 

+ From f58b96d3e8d1cb0dd3666bc74fa673918b586612 Mon Sep 17 00:00:00 2001

+ From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>

+ Date: Mon, 14 Sep 2020 17:58:03 +0200

+ Subject: [PATCH] test-mountpointutil-util: do not assert in test_mnt_id()

+ 

+ https://bugzilla.redhat.com/show_bug.cgi?id=1803070

+ 

+ I *think* this a kernel bug: the mnt_id as listed in /proc/self/mountinfo is different

+ than the one we get from /proc/self/fdinfo/. This only matters when both statx and

+ name_to_handle_at are unavailable and we hit the fallback path that goes through fdinfo:

+ 

+ (gdb) !uname -r

+ 5.6.19-200.fc31.ppc64le

+ 

+ (gdb) !cat /proc/self/mountinfo

+ 697 664 253:0 /var/lib/mock/fedora-31-ppc64le/root / rw,relatime shared:298 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota

+ 698 697 253:0 /var/cache/mock/fedora-31-ppc64le/yum_cache /var/cache/yum rw,relatime shared:299 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota

+ 699 697 253:0 /var/cache/mock/fedora-31-ppc64le/dnf_cache /var/cache/dnf rw,relatime shared:300 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota

+ 700 697 0:32 /mock-selinux-plugin.7me9bfpi /proc/filesystems rw,nosuid,nodev shared:301 master:18 - tmpfs tmpfs rw,seclabel <==========================================================

+ 701 697 0:41 / /sys ro,nosuid,nodev,noexec,relatime shared:302 - sysfs sysfs ro,seclabel

+ 702 701 0:21 / /sys/fs/selinux ro,nosuid,nodev,noexec,relatime shared:306 master:8 - selinuxfs selinuxfs rw

+ 703 697 0:42 / /dev rw,nosuid shared:303 - tmpfs tmpfs rw,seclabel,mode=755

+ 704 703 0:43 / /dev/shm rw,nosuid,nodev shared:304 - tmpfs tmpfs rw,seclabel

+ 705 703 0:45 / /dev/pts rw,nosuid,noexec,relatime shared:307 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=666

+ 706 703 0:6 /btrfs-control /dev/btrfs-control rw,nosuid shared:308 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 707 703 0:6 /loop-control /dev/loop-control rw,nosuid shared:309 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 708 703 0:6 /loop0 /dev/loop0 rw,nosuid shared:310 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 709 703 0:6 /loop1 /dev/loop1 rw,nosuid shared:311 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 710 703 0:6 /loop10 /dev/loop10 rw,nosuid shared:312 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 711 703 0:6 /loop11 /dev/loop11 rw,nosuid shared:313 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 712 703 0:6 /loop2 /dev/loop2 rw,nosuid shared:314 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 713 703 0:6 /loop3 /dev/loop3 rw,nosuid shared:315 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 714 703 0:6 /loop4 /dev/loop4 rw,nosuid shared:316 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 715 703 0:6 /loop5 /dev/loop5 rw,nosuid shared:317 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 716 703 0:6 /loop6 /dev/loop6 rw,nosuid shared:318 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 717 703 0:6 /loop7 /dev/loop7 rw,nosuid shared:319 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 718 703 0:6 /loop8 /dev/loop8 rw,nosuid shared:320 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 719 703 0:6 /loop9 /dev/loop9 rw,nosuid shared:321 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755

+ 720 697 0:44 / /run rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 721 720 0:25 /systemd/nspawn/propagate/9cc8a155d0244558b273f773d2b92142 /run/systemd/nspawn/incoming ro master:12 - tmpfs tmpfs rw,seclabel,mode=755

+ 722 697 0:32 /mock-resolv.dvml91hp /etc/resolv.conf rw,nosuid,nodev shared:322 master:18 - tmpfs tmpfs rw,seclabel

+ 725 697 0:47 / /proc rw,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 603 725 0:47 /sys /proc/sys ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 604 725 0:44 /systemd/inaccessible/reg /proc/kallsyms ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 605 725 0:44 /systemd/inaccessible/reg /proc/kcore ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 606 725 0:44 /systemd/inaccessible/reg /proc/keys ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 607 725 0:44 /systemd/inaccessible/reg /proc/sysrq-trigger ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 608 725 0:44 /systemd/inaccessible/reg /proc/timer_list ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 609 725 0:47 /bus /proc/bus ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 610 725 0:47 /fs /proc/fs ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 611 725 0:47 /irq /proc/irq ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 612 725 0:47 /scsi /proc/scsi ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw

+ 613 703 0:46 / /dev/mqueue rw,nosuid,nodev,noexec,relatime shared:324 - mqueue mqueue rw,seclabel

+ 614 701 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:325 - cgroup2 cgroup rw,seclabel,nsdelegate

+ 615 603 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 616 725 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 617 725 0:44 /.#proc-kmsg5b7a8bcfe6717139//deleted /proc/kmsg rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755

+ 

+ The test process does

+ name_to_handle_at("/proc/filesystems") which returns -EOPNOTSUPP, and then

+ openat(AT_FDCWD, "/proc/filesystems") which returns 4, and then

+ read(open("/proc/self/fdinfo/4", ...)) which gives

+ "pos:\t0\nflags:\t012100000\nmnt_id:\t725\n"

+ 

+ and the "725" is clearly inconsistent with "700" in /proc/self/mountinfo.

+ 

+ We could either drop the fallback path (and fail name_to_handle_at() is not

+ avaliable) or ignore the error in the test. Not sure what is better. I think

+ this issue only occurs sometimes and with older kernels, so probably continuing

+ with the current flaky implementation is better than ripping out the fallback.

+ 

+ Another strace:

+ writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/sys is 603", iov_len=27}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/sys is 603

+ ) = 28

+ name_to_handle_at(AT_FDCWD, "/", {handle_bytes=128 => 12, handle_type=129, f_handle=0x52748401000000008b93e20d}, [697], 0) = 0

+ writev(2</dev/pts/0>, [{iov_base="mnt ids of / is 697", iov_len=19}, {iov_base="\n", iov_len=1}], 2mnt ids of / is 697

+ ) = 20

+ name_to_handle_at(AT_FDCWD, "/proc/kcore", {handle_bytes=128 => 12, handle_type=1, f_handle=0x92ddcfcd2e802d0100000000}, [605], 0) = 0

+ writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/kcore is 605", iov_len=29}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/kcore is 605

+ ) = 30

+ name_to_handle_at(AT_FDCWD, "/dev", {handle_bytes=128 => 12, handle_type=1, f_handle=0x8ae269160c802d0100000000}, [703], 0) = 0

+ writev(2</dev/pts/0>, [{iov_base="mnt ids of /dev is 703", iov_len=22}, {iov_base="\n", iov_len=1}], 2mnt ids of /dev is 703

+ ) = 23

+ name_to_handle_at(AT_FDCWD, "/proc/filesystems", {handle_bytes=128}, 0x7fffe36ddb84, 0) = -1 EOPNOTSUPP (Operation not supported)

+ openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 4</proc/filesystems>

+ openat(AT_FDCWD, "/proc/self/fdinfo/4", O_RDONLY|O_CLOEXEC) = 5</proc/20/fdinfo/4>

+ fstat(5</proc/20/fdinfo/4>, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0

+ fstat(5</proc/20/fdinfo/4>, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0

+ read(5</proc/20/fdinfo/4>, "pos:\t0\nflags:\t012100000\nmnt_id:\t725\n", 2048) = 36

+ read(5</proc/20/fdinfo/4>, "", 1024)    = 0

+ close(5</proc/20/fdinfo/4>)             = 0

+ close(4</proc/filesystems>)             = 0

+ writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/filesystems are 700, 725", iov_len=41}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/filesystems are 700, 725

+ ) = 42

+ writev(2</dev/pts/0>, [{iov_base="the other path for mnt id 725 is /proc", iov_len=38}, {iov_base="\n", iov_len=1}], 2the other path for mnt id 725 is /proc

+ ) = 39

+ writev(2</dev/pts/0>, [{iov_base="Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting.", iov_len=108}, {iov_base="\n", iov_len=1}], 2Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting.

+ ) = 109

+ rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0

+ rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0

+ getpid()                                = 20

+ gettid()                                = 20

+ tgkill(20, 20, SIGABRT)                 = 0

+ rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

+ --- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=20, si_uid=0} ---

+ +++ killed by SIGABRT (core dumped) +++

+ ---

+  src/test/test-mountpoint-util.c | 8 ++++++--

+  1 file changed, 6 insertions(+), 2 deletions(-)

+ 

+ diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c

+ index 30b00ae4d8b..ffe5144b04a 100644

+ --- a/src/test/test-mountpoint-util.c

+ +++ b/src/test/test-mountpoint-util.c

+ @@ -89,8 +89,12 @@ static void test_mnt_id(void) {

+                  /* The ids don't match? If so, then there are two mounts on the same path, let's check if

+                   * that's really the case */

+                  char *t = hashmap_get(h, INT_TO_PTR(mnt_id2));

+ -                log_debug("the other path for mnt id %i is %s\n", mnt_id2, t);

+ -                assert_se(path_equal(p, t));

+ +                log_debug("Path for mnt id %i from /proc/self/mountinfo is %s\n", mnt_id2, t);

+ +

+ +                if (!path_equal(p, t))

+ +                        /* Apparent kernel bug in /proc/self/fdinfo */

+ +                        log_warning("Bad mount id given for %s: %d, should be %d",

+ +                                    p, mnt_id2, mnt_id);

+          }

+  }

+  

@@ -0,0 +1,3 @@ 

+ [suppress_file]

+ # This shared object is private to systemd

+ file_name_regexp=libsystemd-shared-.*.so

file modified
+32 -3
@@ -21,8 +21,13 @@ 

  o_rpm_macros = open('.file-list-rpm-macros', 'w')

  o_devel = open('.file-list-devel', 'w')

  o_container = open('.file-list-container', 'w')

+ o_networkd = open('.file-list-networkd', 'w')

+ o_oomd_defaults = open('.file-list-oomd-defaults', 'w')

  o_remote = open('.file-list-remote', 'w')

+ o_resolve = open('.file-list-resolve', 'w')

  o_tests = open('.file-list-tests', 'w')

+ o_standalone_tmpfiles = open('.file-list-standalone-tmpfiles', 'w')

+ o_standalone_sysusers = open('.file-list-standalone-sysusers', 'w')

  o_rest = open('.file-list-rest', 'w')

  for file in files(buildroot):

      n = file.path[1:]
@@ -51,10 +56,10 @@ 

          o = o_pam

      elif '/rpm/' in n:

          o = o_rpm_macros

-     elif re.search(r'/lib.*\.pc|/man3/|/usr/include|(?<!/libsystemd-shared-...).so$', n):

-         o = o_devel

      elif '/usr/lib/systemd/tests' in n:

          o = o_tests

+     elif re.search(r'/lib.*\.pc|/man3/|/usr/include|(?<!/libsystemd-shared-...).so$', n):

+         o = o_devel

      elif re.search(r'''journal-(remote|gateway|upload)|

                         systemd-remote\.conf|

                         /usr/share/systemd/gatewayd|
@@ -69,10 +74,15 @@ 

                         /machine.slice|

                         /machines.target|

                         var-lib-machines.mount|

-                        network/80-container-v[ez]|

                         org.freedesktop.(import|machine)1

      ''', n, re.X):

          o = o_container

+     elif re.search(r'''/usr/lib/systemd/network/80-|

+                        networkd|

+                        networkctl|

+                        org.freedesktop.network1

+     ''', n, re.X):

+         o = o_networkd

      elif '.so.' in n:

          o = o_libs

      elif re.search(r'''udev(?!\.pc)|
@@ -109,6 +119,23 @@ 

                         /modprobe.d

      ''', n, re.X):

          o = o_udev

+     elif re.search(r'''resolvectl|

+                        resolved|

+                        systemd-resolve|

+                        resolvconf|

+                        resolve1\.

+     ''', n, re.X):

+         # keep only nss-resolve in systemd

+         o = o_resolve

+     elif re.search(r'10-oomd-.*defaults.conf|lib/systemd/oomd.conf.d', n, re.X):

+         o = o_oomd_defaults

+     elif n.endswith('.standalone'):

+         if 'tmpfiles' in n:

+             o = o_standalone_tmpfiles

+         elif 'sysusers' in n:

+             o = o_standalone_sysusers

+         else:

+             assert False, 'Found .standalone not belonging to known packages'

      else:

          o = o_rest

  
@@ -118,6 +145,8 @@ 

              prefix += ' '

      elif file.is_dir() and not file.is_symlink():

          prefix = '%dir '

+     elif 'README' in n:

+         prefix = '%doc '

      elif n.startswith('/etc'):

          prefix = '%config(noreplace) '

      else:

@@ -0,0 +1,20 @@ 

+ ########################################

+ ## <summary>

+ ##	Allows the caller to use the SELinux status page.

+ ## </summary>

+ ## <param name="domain">

+ ##	<summary>

+ ##	Domain allowed access.

+ ##	</summary>

+ ## </param>

+ ## <rolecap/>

+ #

+ interface(`selinux_use_status_page',`

+ 	gen_require(`

+ 		type security_t;

+ 	')

+ 

+ 	dev_search_sysfs($1)

+ 	allow $1 security_t:dir list_dir_perms;

+ 	allow $1 security_t:file mmap_read_file_perms;

+ ')

@@ -0,0 +1,68 @@ 

+ policy_module(systemd_hs,0.0.1)

+ 

+ # systemd overrides for 247

+ gen_require(`

+ 	type avahi_t;

+ 	type cgroup_t;

+ 	type init_t;

+ 	type init_var_run_t;

+ 	type initrc_t;

+ 	class dbus send_msg;

+ 	type install_t;

+ 	type kmsg_device_t;

+ 	type policykit_auth_t;

+ 	type policykit_t;

+ 	type proc_kmsg_t;

+ 	type rpm_t;

+ 	type system_dbusd_t;

+ 	type system_dbusd_var_run_t;

+ 	type systemd_hostnamed_t;

+ 	type systemd_localed_t;

+ 	type systemd_logind_t;

+ 	type systemd_machined_t;

+ 	type systemd_resolved_t;

+ 	type systemd_tmpfiles_t;

+ 	type security_t;

+ 	type sssd_t;

+ 	type syslogd_t;

+ 	type udev_var_run_t;

+ 	type user_tmp_t;

+ 	type useradd_t;

+ 	type xdm_t;

+ ')

+ 

+ allow avahi_t init_var_run_t:dir read;

+ allow init_t kmsg_device_t:chr_file mounton;

+ allow init_t proc_kmsg_t:file { getattr mounton };

+ allow init_t system_dbusd_var_run_t:sock_file read;

+ allow init_t systemd_machined_t:unix_stream_socket connectto;

+ allow policykit_auth_t init_var_run_t:dir read;

+ allow policykit_auth_t systemd_machined_t:unix_stream_socket connectto;

+ allow policykit_t systemd_machined_t:unix_stream_socket connectto;

+ allow sssd_t cgroup_t:filesystem getattr;

+ allow syslogd_t user_tmp_t:lnk_file read;

+ allow system_dbusd_t systemd_machined_t:unix_stream_socket connectto;

+ allow systemd_hostnamed_t init_var_run_t:dir write;

+ allow systemd_hostnamed_t init_var_run_t:file { getattr ioctl open read };

+ allow systemd_hostnamed_t initrc_t:dbus send_msg;

+ allow systemd_hostnamed_t install_t:dbus send_msg;

+ allow systemd_hostnamed_t udev_var_run_t:file getattr;

+ allow systemd_hostnamed_t udev_var_run_t:file open;

+ allow systemd_hostnamed_t udev_var_run_t:file read;

+ allow systemd_logind_t self:netlink_selinux_socket bind;

+ allow systemd_logind_t self:netlink_selinux_socket create;

+ allow systemd_logind_t systemd_machined_t:unix_stream_socket connectto;

+ allow systemd_logind_t user_tmp_t:chr_file unlink;

+ allow systemd_machined_t init_var_run_t:sock_file create;

+ allow sssd_t cgroup_t:dir search;

+ allow sssd_t cgroup_t:filesystem getattr;

+ allow useradd_t init_var_run_t:dir read;

+ allow xdm_t systemd_machined_t:unix_stream_socket connectto;

+ 

+ selinux_use_status_page(init_t)

+ selinux_use_status_page(rpm_t)

+ selinux_use_status_page(systemd_hostnamed_t)

+ selinux_use_status_page(systemd_localed_t)

+ selinux_use_status_page(systemd_logind_t)

+ selinux_use_status_page(systemd_resolved_t)

+ selinux_use_status_page(systemd_tmpfiles_t)

@@ -12,17 +12,17 @@ 

      home="$5"

      shell="$6"

  

- [ "$desc" = '-' ] && desc=

- [ "$home" = '-' -o "$home" = '' ] && home=/

- [ "$shell" = '-' -o "$shell" = '' ] && shell=/sbin/nologin

+     [ "$desc" = '-' ] && desc=

+     { [ "$home" = '-' ] || [ "$home" = '' ]; } && home=/

+     { [ "$shell" = '-' ] || [ "$shell" = '' ]; } && shell=/sbin/nologin

  

- if [ "$uid" = '-' -o "$uid" = '' ]; then

-     cat <<EOF

+     if [ "$uid" = '-' ] || [ "$uid" = '' ]; then

+         cat <<EOF

  getent passwd '$user' >/dev/null || \\

      useradd -r -g '$group' -d '$home' -s '$shell' -c '$desc' '$user'

  EOF

- else

-     cat <<EOF

+     else

+         cat <<EOF

  if ! getent passwd '$user' >/dev/null ; then

      if ! getent passwd '$uid' >/dev/null ; then

          useradd -r -u '$uid' -g '$group' -d '$home' -s /sbin/nologin -c '$desc' '$user'
@@ -32,29 +32,29 @@ 

  fi

  

  EOF

- fi

+     fi

  }

  

  group() {

      group="$1"

      gid="$2"

- if [ "$gid" = '-' ]; then

-     cat <<EOF

- getent group '$group' >/dev/null || groupadd -r '$group'

- EOF

- else

-     cat <<EOF

- getent group '$group' >/dev/null || groupadd -f -g '$gid' -r '$group'

- EOF

- fi

+     if [ "$gid" = '-' ]; then

+         cat <<-EOF

+ 	getent group '$group' >/dev/null || groupadd -r '$group'

+ 	EOF

+     else

+         cat <<-EOF

+ 	getent group '$group' >/dev/null || groupadd -f -g '$gid' -r '$group'

+ 	EOF

+     fi

  }

  

  parse() {

-     while read line || [ "$line" ]; do

-         [ "${line:0:1}" = '#' -o "${line:0:1}" = ';' ] && continue

+     while read -r line || [ -n "$line" ] ; do

+         { [ "${line:0:1}" = '#' ] || [ "${line:0:1}" = ';' ]; } && continue

          line="${line## *}"

          [ -z "$line" ] && continue

-         eval arr=( $line )

+         eval "arr=( $line )"

          case "${arr[0]}" in

              ('u')

                  group "${arr[1]}" "${arr[2]}"
@@ -74,6 +74,6 @@ 

  

  for fn in "$@"; do

      [ -e "$fn" ] || continue

-     echo "# generated from $(basename $fn)"

-     parse < "$fn"

+     echo "# generated from $(basename "$fn")"

+     parse <"$fn"

  done

file modified
+39 -61
@@ -1,111 +1,89 @@ 

  #  -*- Mode: rpm-spec; indent-tabs-mode: nil -*- */

- #  SPDX-License-Identifier: LGPL-2.1+

+ #  SPDX-License-Identifier: LGPL-2.1-or-later

  #

  #  This file is part of systemd.

  #

- #  Copyright 2015 Zbigniew Jędrzejewski-Szmek

  #  Copyright 2018 Neal Gompa

- #

- #  systemd is free software; you can redistribute it and/or modify it

- #  under the terms of the GNU Lesser General Public License as published by

- #  the Free Software Foundation; either version 2.1 of the License, or

- #  (at your option) any later version.

- #

- #  systemd is distributed in the hope that it will be useful, but

- #  WITHOUT ANY WARRANTY; without even the implied warranty of

- #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

- #  Lesser General Public License for more details.

- #

- #  You should have received a copy of the GNU Lesser General Public License

- #  along with systemd; If not, see <http://www.gnu.org/licenses/>.

  

  # The contents of this are an example to be copied into systemd.spec.

  #

- # Minimum rpm version supported: 4.13.0

+ # Minimum rpm version supported: 4.14.0

  

  %transfiletriggerin -P 900900 -- /usr/lib/systemd/system /etc/systemd/system

  # This script will run after any package is initially installed or

  # upgraded. We care about the case where a package is initially

  # installed, because other cases are covered by the *un scriptlets,

  # so sometimes we will reload needlessly.

- if test -d /run/systemd/system; then

-   %{_bindir}/systemctl daemon-reload

+ if test -d "/run/systemd/system"; then

+   %{_bindir}/systemctl daemon-reload || :

+   %{_bindir}/systemctl reload-or-restart --marked || :

  fi

  

- %transfiletriggerun -- /usr/lib/systemd/system /etc/systemd/system

+ %transfiletriggerpostun -P 1000100 -- /usr/lib/systemd/system /etc/systemd/system

  # On removal, we need to run daemon-reload after any units have been

- # removed. %transfiletriggerpostun would be ideal, but it does not get

- # executed for some reason.

+ # removed.

  # On upgrade, we need to run daemon-reload after any new unit files

  # have been installed, but before %postun scripts in packages get

- # executed. %transfiletriggerun gets the right list of files

- # but it is invoked too early (before changes happen).

- # %filetriggerpostun happens at the right time, but it fires for

- # every package.

- # To execute the reload at the right time, we create a state

- # file in %transfiletriggerun and execute the daemon-reload in

- # the first %filetriggerpostun.

- 

+ # executed.

  if test -d "/run/systemd/system"; then

-     mkdir -p "%{_localstatedir}/lib/rpm-state/systemd"

-     touch "%{_localstatedir}/lib/rpm-state/systemd/needs-reload"

+   %{_bindir}/systemctl daemon-reload || :

  fi

  

- %filetriggerpostun -P 1000100 -- /usr/lib/systemd/system /etc/systemd/system

- if test -f "%{_localstatedir}/lib/rpm-state/systemd/needs-reload"; then

-     rm -rf "%{_localstatedir}/lib/rpm-state/systemd"

-     %{_bindir}/systemctl daemon-reload

+ %transfiletriggerpostun -P 10000 -- /usr/lib/systemd/system /etc/systemd/system

+ # We restart remaining services that should be restarted here.

+ if test -d "/run/systemd/system"; then

+   %{_bindir}/systemctl reload-or-restart --marked || :

  fi

  

- %transfiletriggerin -P 100700 -- /usr/lib/sysusers.d

+ %transfiletriggerin -P 1000700 -- /usr/lib/sysusers.d

  # This script will process files installed in /usr/lib/sysusers.d to create

  # specified users automatically. The priority is set such that it

  # will run before the tmpfiles file trigger.

- if test -d /run/systemd/system; then

+ if test -d "/run/systemd/system"; then

    %{_bindir}/systemd-sysusers || :

  fi

  

- %transfiletriggerin -P 100500 -- /usr/lib/tmpfiles.d

- # This script will process files installed in /usr/lib/tmpfiles.d to create

- # tmpfiles automatically. The priority is set such that it will run

- # after the sysusers file trigger, but before any other triggers.

- if test -d /run/systemd/system; then

-   %{_bindir}/systemd-tmpfiles --create || :

- fi

- 

- %transfiletriggerin udev -- /usr/lib/udev/hwdb.d

+ %transfiletriggerin -P 1000700 udev -- /usr/lib/udev/hwdb.d

  # This script will automatically invoke hwdb update if files have been

  # installed or updated in /usr/lib/udev/hwdb.d.

- if test -d /run/systemd/system; then

+ if test -d "/run/systemd/system"; then

    %{_bindir}/systemd-hwdb update || :

  fi

  

- %transfiletriggerin -- /usr/lib/systemd/catalog

+ %transfiletriggerin -P 1000700 -- /usr/lib/systemd/catalog

  # This script will automatically invoke journal catalog update if files

  # have been installed or updated in /usr/lib/systemd/catalog.

- if test -d /run/systemd/system; then

+ if test -d "/run/systemd/system"; then

    %{_bindir}/journalctl --update-catalog || :

  fi

  

- %transfiletriggerin udev -- /usr/lib/udev/rules.d

+ %transfiletriggerin -P 1000700 -- /usr/lib/binfmt.d

+ # This script will automatically apply binfmt rules if files have been

+ # installed or updated in /usr/lib/binfmt.d.

+ if test -d "/run/systemd/system"; then

+   # systemd-binfmt might fail if binfmt_misc kernel module is not loaded

+   # during install

+   /usr/lib/systemd/systemd-binfmt || :

+ fi

+ 

+ %transfiletriggerin -P 1000600 -- /usr/lib/tmpfiles.d

+ # This script will process files installed in /usr/lib/tmpfiles.d to create

+ # tmpfiles automatically. The priority is set such that it will run

+ # after the sysusers file trigger, but before any other triggers.

+ if test -d "/run/systemd/system"; then

+   %{_bindir}/systemd-tmpfiles --create || :

+ fi

+ 

+ %transfiletriggerin -P 1000600 udev -- /usr/lib/udev/rules.d

  # This script will automatically update udev with new rules if files

  # have been installed or updated in /usr/lib/udev/rules.d.

  if test -e /run/udev/control; then

    %{_bindir}/udevadm control --reload || :

  fi

  

- %transfiletriggerin -- /usr/lib/sysctl.d

+ %transfiletriggerin -P 1000500 -- /usr/lib/sysctl.d

  # This script will automatically apply sysctl rules if files have been

  # installed or updated in /usr/lib/sysctl.d.

- if test -d /run/systemd/system; then

+ if test -d "/run/systemd/system"; then

    /usr/lib/systemd/systemd-sysctl || :

  fi

- 

- %transfiletriggerin -- /usr/lib/binfmt.d

- # This script will automatically apply binfmt rules if files have been

- # installed or updated in /usr/lib/binfmt.d.

- if test -d /run/systemd/system; then

-   # systemd-binfmt might fail if binfmt_misc kernel module is not loaded

-   # during install

-   /usr/lib/systemd/systemd-binfmt || :

- fi

file modified
+778 -205
@@ -1,15 +1,4 @@ 

- # Meson settings

- %global _vpath_srcdir .

- %global _vpath_builddir %{_target_platform}

- %global __global_cflags  %{optflags}

- %global __global_cxxflags  %{optflags}

- %global __global_fflags  %{optflags} -I%_fmoddir

- %global __global_fcflags %{optflags} -I%_fmoddir

- %global __global_ldflags -Wl,-z,relro %{_hardened_ldflags}

- 

- %define _python_bytecompile_errors_terminate_build 0

- 

- #global commit 7f56c26d1041e686efa72b339250a98fb6ee8f00

+ #global commit c4b843473a75fb38ed5bf54e9d3cfb1cb3719efa

  %{?commit:%global shortcommit %(c=%{commit}; echo ${c:0:7})}

  

  %global stable 1
@@ -23,83 +12,52 @@ 

  %global system_unit_dir %{pkgdir}/system

  %global user_unit_dir %{pkgdir}/user

  

- %if 0%{?facebook}

- %if 0%{?el7}

- ### The version of meson and redhat-rpm-config is not in sync in C7.

- ### Copied from the 'redhat-rpm-config-123-1' version of /usr/lib/rpm/redhat/macros

- ### to support the building of systemd via meson that uses the

- ### set_build_flags macro.

- %global _ld_symbols_flags              %{?_strict_symbol_defs_build:-Wl,-z,defs}

- 

- #==============================================================================

- # ---- compiler flags.

- 

- # C compiler flags.  This is traditionally called CFLAGS in makefiles.

- # Historically also available as %%{optflags}, and %%build sets the

- # environment variable RPM_OPT_FLAGS to this value.

- %global build_cflags %{optflags}

- 

- # C++ compiler flags.  This is traditionally called CXXFLAGS in makefiles.

- %global build_cxxflags %{optflags}

- 

- # Fortran compiler flags.  Makefiles use both FFLAGS and FCFLAGS as

- # the corresponding variable names.

- %global build_fflags %{optflags} -I%{_fmoddir}

- 

- # Link editor flags.  This is usually called LDFLAGS in makefiles.

- # (Some makefiles use LFLAGS instead.)  The default value assumes that

- # the flags, while intended for ld, are still passed through the gcc

- # compiler driver.  At the beginning of %%build, the environment

- # variable RPM_LD_FLAGS to this value.

- %global build_ldflags -Wl,-z,relro %{_ld_symbols_flags} %{_hardened_ldflags}

- 

- # Expands to shell code to seot the compiler/linker environment

- # variables CFLAGS, CXXFLAGS, FFLAGS, FCFLAGS, LDFLAGS if they have

- # not been set already.  RPM_OPT_FLAGS and RPM_LD_FLAGS have already

- # been set implicitly at the start of the %%build section.

- %global set_build_flags \

-   CFLAGS="${CFLAGS:-%{build_cflags}}" ; export CFLAGS ; \

-   CXXFLAGS="${CXXFLAGS:-%{build_cxxflags}}" ; export CXXFLAGS ; \

-   FFLAGS="${FFLAGS:-%{build_fflags}}" ; export FFLAGS ; \

-   FCFLAGS="${FCFLAGS:-%{build_fflags}}" ; export FCFLAGS ; \

-   LDFLAGS="${LDFLAGS:-%{build_ldflags}}" ; export LDFLAGS;

- 

- ### Copied from the rpm-4.14.2-36 version of /usr/lib/rpm/platform/x86_64-linux/macros

- ### to support the building of systemd via meson that uses the

- ### _smp_build_ncpus macro

- %global _smp_build_ncpus %([ -z "$RPM_BUILD_NCPUS" ] \\\

- 	&& RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"; \\\

-         ncpus_max=%{?_smp_ncpus_max}; \\\

-         if [ -n "$ncpus_max" ] && [ "$ncpus_max" -gt 0 ] && [ "$RPM_BUILD_NCPUS" -gt "$ncpus_max" ]; then RPM_BUILD_NCPUS="$ncpus_max"; fi; \\\

-         echo "$RPM_BUILD_NCPUS";)

- 

- %global _smp_mflags -j%{_smp_build_ncpus}

- %endif

+ %if 0%{?__isa_bits} == 64

+ %global elf_bits (64bit)

+ %global elf_suffix ()%{elf_bits}

  %endif

  

  # Bootstrap may be needed to break intercircular dependencies with

  # cryptsetup, e.g. when re-building cryptsetup on a json-c SONAME-bump.

  %bcond_with    bootstrap

  %bcond_without tests

+ %bcond_without lto

+ 

+ # Support for quick builds with rpmbuild --build-in-place.

+ # See README.build-in-place.

+ %bcond_with    inplace

+ 

+ %if 0%{?facebook}

+ %bcond_with selinux

+ %else

+ %bcond_without selinux

+ %endif

+ 

+ # Remove this when the macro exists in CentOS

+ %global version_no_tilde %(c=%{version}; echo ${c}|tr '~' '-')

  

  Name:           systemd

  Url:            https://www.freedesktop.org/wiki/Software/systemd

- Version:        246.1

- Release:        1.fb6

+ %if %{without inplace}

+ Version:        249.4

+ Release:        2.9%{?dist}

+ %else

+ # determine the build information from local checkout

+ Version:        %(tools/meson-vcs-tag.sh . error | sed -r 's/-([0-9])/.^\1/; s/-g/_g/')

+ Release:        1

+ %endif

  # For a breakdown of the licensing, see README

  License:        LGPLv2+ and MIT and GPLv2+

  Summary:        System and Service Manager

  

- %global github_version %(c=%{version}; echo ${c}|tr '~' '-')

- 

  # download tarballs with "spectool -g systemd.spec"

  %if %{defined commit}

  Source0:        https://github.com/systemd/systemd%{?stable:-stable}/archive/%{commit}/%{name}-%{shortcommit}.tar.gz

  %else

  %if 0%{?stable}

- Source0:        https://github.com/systemd/systemd-stable/archive/v%{github_version}/%{name}-%{github_version}.tar.gz

+ Source0:        https://github.com/systemd/systemd-stable/archive/v%{version_no_tilde}/%{name}-%{version_no_tilde}.tar.gz

  %else

- Source0:        https://github.com/systemd/systemd/archive/v%{github_version}/%{name}-%{github_version}.tar.gz

+ Source0:        https://github.com/systemd/systemd/archive/v%{version_no_tilde}/%{name}-%{version_no_tilde}.tar.gz

  %endif

  %endif

  # This file must be available before %%prep.
@@ -115,36 +73,80 @@ 

  Source10:       systemd-udev-trigger-no-reload.conf

  Source11:       20-grubby.install

  Source12:       systemd-user

+ Source13:       libsystemd-shared.abignore

+ 

+ Source14:       10-oomd-defaults.conf

+ Source15:       10-oomd-root-slice-defaults.conf

+ Source16:       10-oomd-user-service-defaults.conf

  

  Source21:       macros.sysusers

  Source22:       sysusers.attr

  Source23:       sysusers.prov

  Source24:       sysusers.generate-pre.sh

  

+ # Needed for selinux subpackage

+ Source100:      Makefile.selinux

+ Source101:      systemd_hs.te

+ Source102:      systemd_hs.if

+ 

  %if 0

  GIT_DIR=../../src/systemd/.git git format-patch-ab --no-signature -M -N v235..v235-stable

  i=1; for j in 00*patch; do printf "Patch%04d:      %s\n" $i $j; i=$((i+1));done|xclip

  GIT_DIR=../../src/systemd/.git git diffab -M v233..master@{2017-06-15} -- hwdb/[67]* hwdb/parse_hwdb.py > hwdb.patch

  %endif

  

- Patch0002:      0001-Revert-test-path-increase-timeout.patch

- Patch0003:      0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch

+ # Backports of patches from upstream (0000–0499)

+ #

+ # Any patches which are "in preparation" upstream should be listed

+ # here, rather than in the next section. Packit CI will drop any

+ # patches in this range before applying upstream pull requests.

+ 

+ %if 0%{?facebook}

+ Patch0001:      0001-rpm-don-t-specify-the-full-path-for-systemctl-and-ot.patch

+ Patch0002:      0002-rpm-use-a-helper-script-to-actually-invoke-systemctl.patch

+ Patch0003:      0003-rpm-call-needs-restart-in-parallel.patch

+ Patch0004:      0004-rpm-restart-user-services-at-the-end-of-the-transact.patch

+ Patch0005:      0005-update-helper-also-add-user-reexec-verb.patch

+ 

+ # PR 18621: FB variant of quieting "proc: Bad value for 'hidepid'" messages

+ Patch0006:      18621-fb.patch

+ %else

+ # PR 18621: Quiet "proc: Bad value for 'hidepid'" messages

+ Patch0006:      https://github.com/systemd/systemd/pull/18621.patch

+ %endif

+ 

+ # PRs to support additional systemd.network and systemd.link features

+ Patch0007:      https://github.com/systemd/systemd/pull/20743.patch

+ Patch0008:      https://github.com/systemd/systemd/pull/20458.patch

+ Patch0009:      https://github.com/systemd/systemd/pull/20472.patch

+ Patch0010:      https://github.com/systemd/systemd/pull/20477.patch

+ Patch0011:      https://github.com/systemd/systemd/pull/20484.patch

+ Patch0012:      https://github.com/systemd/systemd/pull/20489.patch

+ Patch0013:      https://github.com/systemd/systemd/pull/20450.patch

+ Patch0014:      https://github.com/systemd/systemd/pull/20541.patch

+ Patch0015:      https://github.com/systemd/systemd/pull/20729.patch

+ Patch0016:      https://github.com/systemd/systemd/pull/20828.patch

+ # Part of PR #20892; it was difficult to backport the whole PR

+ Patch0017:      50783f91d44b1978c0e4ba62283131fac75d3745_cherrypicked.patch

+ 

+ # PR 20875: allow verifying hidden (dot) files again

+ Patch0018:      https://github.com/systemd/systemd/pull/20875.patch

  

- Patch0004:      0001-test-acl-util-output-more-debug-info.patch

- Patch0005:      0001-Do-not-assert-in-test_add_acls_for_user.patch

+ # PR 20978: serialize bpf device programs across reloads/reexecs

+ Patch0019:      https://github.com/systemd/systemd/pull/20978.patch

  

- Patch1001:      FB--Add-FusionIO-device--dev-fio-persistante-storage-udev-rule.patch

+ # PR 20676: don't rewrite sysctls that are already set

+ Patch0020:      20676_cherrypicked.patch

  

- Patch1002:      16838_16857_improve_path_search.patch

- Patch1003:      16940_cleanup_socket_econn_handling.patch

- Patch1004:      17031_propagate_start_limit_hit.patch

- Patch1005:      17082_nspawn_tty_tweaks.patch

+ # PR 21221: Fixes non-deterministic Slice= assignments

+ Patch0021:      21221.patch

  

- Patch1006:      0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch

- Patch1007:      0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch

- Patch1008:      0003-timer-add-new-feature-FixedRandomDelay.patch

+ # Downstream-only patches (0500–9999)

  

- Patch1009:      16803_fix_asserts_conditions.patch

+ # https://github.com/systemd/systemd/pull/17050

+ Patch0501:      https://github.com/systemd/systemd/pull/17050/commits/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch

+ # Downgrade sysv-generator messages from warning to debug

+ Patch0502:      0001-sysv-generator-downgrade-log-warning-about-autogener.patch

  

  %ifarch %{ix86} x86_64 aarch64

  %global have_gnu_efi 1
@@ -164,8 +166,9 @@ 

  BuildRequires:  cryptsetup-devel

  %endif

  BuildRequires:  dbus-devel

+ BuildRequires:  /usr/sbin/sfdisk

  # /usr/bin/getfacl is needed by test-acl-util

- BuildRequires:  acl

+ BuildRequires:  /usr/bin/getfacl

  BuildRequires:  libacl-devel

  BuildRequires:  gobject-introspection-devel

  BuildRequires:  libblkid-devel
@@ -183,10 +186,13 @@ 

  BuildRequires:  libgcrypt-devel

  BuildRequires:  libgpg-error-devel

  BuildRequires:  gnutls-devel

- BuildRequires:  qrencode-devel

  BuildRequires:  libmicrohttpd-devel

  BuildRequires:  libxkbcommon-devel

  BuildRequires:  iptables-devel

+ BuildRequires:  pkgconfig(tss2-esys)

+ BuildRequires:  pkgconfig(tss2-rc)

+ BuildRequires:  pkgconfig(tss2-mu)

+ BuildRequires:  systemtap-sdt-devel

  BuildRequires:  libxslt

  BuildRequires:  docbook-style-xsl

  BuildRequires:  pkgconfig
@@ -194,24 +200,24 @@ 

  BuildRequires:  gawk

  BuildRequires:  tree

  BuildRequires:  hostname

- %if 0%{?el7}

- BuildRequires:  python34-devel

- BuildRequires:  python34-lxml

- %else

  BuildRequires:  python3-devel

  BuildRequires:  python3-lxml

- %endif

- BuildRequires:  python3

- %global __python3 /usr/bin/python3

+ BuildRequires:  python3-jinja2

  %if 0%{?have_gnu_efi}

  BuildRequires:  gnu-efi gnu-efi-devel

  %endif

  BuildRequires:  libseccomp-devel

+ %if 0%{?el8}

+ BuildRequires:  meson >= 0.57

+ %else

  BuildRequires:  meson >= 0.43

+ %endif

  BuildRequires:  gettext

  # We use RUNNING_ON_VALGRIND in tests, so the headers need to be available

  BuildRequires:  valgrind-devel

  BuildRequires:  pkgconfig(bash-completion)

+ BuildRequires:  perl

+ BuildRequires:  perl(IPC::SysV)

  

  Requires(post): coreutils

  Requires(post): sed
@@ -220,14 +226,14 @@ 

  # systemd-machine-id-setup requires libssl

  Requires(post): openssl-libs

  Requires(pre):  coreutils

- Requires(pre):  /usr/bin/getent

- Requires(pre):  /usr/sbin/groupadd

  Requires:       dbus >= 1.9.18

  Requires:       %{name}-pam = %{version}-%{release}

- Requires:       %{name}-rpm-macros = %{version}-%{release}

+ Requires:       (%{name}-rpm-macros = %{version}-%{release} if rpm-build)

  Requires:       %{name}-libs = %{version}-%{release}

+ %{?fedora:Recommends:     %{name}-networkd = %{version}-%{release}}

+ %{?fedora:Recommends:     %{name}-resolved = %{version}-%{release}}

  Recommends:     diffutils

- Requires:       util-linux

+ Requires:       (util-linux-core or util-linux)

  Recommends:     libxkbcommon%{?_isa}

  Provides:       /bin/systemctl

  Provides:       /sbin/shutdown
@@ -237,14 +243,33 @@ 

  Provides:       system-setup-keyboard = 0.9

  # systemd-sysv-convert was removed in f20: https://fedorahosted.org/fpc/ticket/308

  Obsoletes:      systemd-sysv < 206

+ %if 0%{?facebook} == 0

  # self-obsoletes so that dnf will install new subpackages on upgrade (#1260394)

- Obsoletes:      %{name} < 229-5

+ Obsoletes:      %{name} < 249~~

+ Conflicts:      initscripts < 9.56.1

+ %endif

  Provides:       systemd-sysv = 206

  %if 0%{?fedora}

  Conflicts:      fedora-release < 23-0.12

  %endif

  Obsoletes:      timedatex < 0.6-3

  Provides:       timedatex = 0.6-3

+ Conflicts:      %{name}-standalone-tmpfiles < %{version}-%{release}

+ Obsoletes:      %{name}-standalone-tmpfiles < %{version}-%{release}

+ Conflicts:      %{name}-standalone-sysusers < %{version}-%{release}

+ Obsoletes:      %{name}-standalone-sysusers < %{version}-%{release}

+ 

+ # Recommends to replace normal Requires deps for stuff that is dlopen()ed

+ Recommends:     libidn2.so.0%{?elf_suffix}

+ Recommends:     libidn2.so.0(IDN2_0.0.0)%{?elf_bits}

+ Recommends:     libpcre2-8.so.0%{?elf_suffix}

+ Recommends:     libpwquality.so.1%{?elf_suffix}

+ Recommends:     libpwquality.so.1(LIBPWQUALITY_1.0)%{?elf_bits}

+ 

+ %if %{with selinux}

+ # Force the SELinux module to be installed

+ Requires:       %{name}-selinux = %{version}-%{release}

+ %endif

  

  %description

  systemd is a system and service manager that runs as PID 1 and starts
@@ -324,16 +349,14 @@ 

  Requires(postun): systemd

  Requires(post): grep

  Requires:       kmod >= 18-4

- %if 0%{?facebook}

- # obsolete parent package so that dnf will install new subpackage on upgrade (#1260394)

- Obsoletes:      %{name} < 229-5

- %else

+ %if 0%{?facebook} == 0

  # https://bodhi.fedoraproject.org/updates/FEDORA-2020-dd43dd05b1

  Obsoletes:      systemd < 245.6-1

  %endif

  Provides:       udev = %{version}

  Provides:       udev%{_isa} = %{version}

  Obsoletes:      udev < 183

+ 

  # https://bugzilla.redhat.com/show_bug.cgi?id=1377733#c9

  Suggests:       systemd-bootchart

  # https://bugzilla.redhat.com/show_bug.cgi?id=1408878
@@ -385,6 +408,35 @@ 

  This package contains systemd-journal-gatewayd,

  systemd-journal-remote, and systemd-journal-upload.

  

+ %package networkd

+ Summary:        System daemon that manages network configurations

+ Requires:       %{name}%{?_isa} = %{version}-%{release}

+ License:        LGPLv2+

+ 

+ %description networkd

+ systemd-networkd is a system service that manages networks. It detects

+ and configures network devices as they appear, as well as creating virtual

+ network devices.

+ 

+ %package resolved

+ Summary:        Network Name Resolution manager

+ Requires:       %{name}%{?_isa} = %{version}-%{release}

+ 

+ %description resolved

+ systemd-resolved is a system service that provides network name resolution

+ to local applications. It implements a caching and validating DNS/DNSSEC

+ stub resolver, as well as an LLMNR and MulticastDNS resolver and responder.

+ 

+ %package oomd-defaults

+ Summary:        Configuration files for systemd-oomd

+ Requires:       %{name} = %{version}-%{release}

+ License:        LGPLv2+

+ BuildArch:      noarch

+ 

+ %description oomd-defaults

+ A set of drop-in files for systemd units to enable action from systemd-oomd,

+ a userspace out-of-memory (OOM) killer.

+ 

  %package tests

  Summary:       Internal unit tests for systemd

  Requires:      %{name}%{?_isa} = %{version}-%{release}
@@ -394,24 +446,49 @@ 

  "Installed tests" that are usually run as part of the build system.

  They can be useful to test systemd internals.

  

+ %if %{with selinux}

+ %package selinux

+ Summary:        SELinux module for systemd

+ BuildArch:      noarch

+ BuildRequires:  bzip2

+ BuildRequires:  make

+ BuildRequires:  selinux-policy

+ BuildRequires:  selinux-policy-devel

+ Requires(post): selinux-policy-base >= %{_selinux_policy_version}

+ Requires(post): policycoreutils

+ Requires(post): policycoreutils-python-utils

+ Requires(pre):  libselinux-utils

+ Requires(post): libselinux-utils

+ 

+ %description selinux

+ This package provides the SELinux policy module to ensure systemd

+ runs properly under an environment with SELinux enabled.

+ %endif

+ 

  %prep

- %autosetup -n %{?commit:%{name}%{?stable:-stable}-%{commit}}%{!?commit:%{name}%{?stable:-stable}-%{github_version}} -p1

+ %autosetup -n %{?commit:%{name}%{?stable:-stable}-%{commit}}%{!?commit:%{name}%{?stable:-stable}-%{version_no_tilde}} -p1

+ 

+ %if %{with selinux}

+ mkdir selinux

+ cp %SOURCE100 %SOURCE101 %SOURCE102 selinux

+ %endif

  

  %build

  %define ntpvendor %(source /etc/os-release; echo ${ID})

  %{!?ntpvendor: echo 'NTP vendor zone is not set!'; exit 1}

  

  CONFIGURE_OPTS=(

+         -Dmode=release

          -Dsysvinit-path=/etc/rc.d/init.d

          -Drc-local=/etc/rc.d/rc.local

          -Dntp-servers='0.%{ntpvendor}.pool.ntp.org 1.%{ntpvendor}.pool.ntp.org 2.%{ntpvendor}.pool.ntp.org 3.%{ntpvendor}.pool.ntp.org'

+         -Ddns-servers=

          -Duser-path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin

          -Dservice-watchdog=

          -Ddev-kvm-mode=0666

          -Dkmod=true

          -Dxkbcommon=true

          -Dblkid=true

-         -Dfdisk=true

          -Dseccomp=true

          -Dima=true

          -Dselinux=true
@@ -425,6 +502,7 @@ 

          -Dpam=true

          -Dacl=true

          -Dsmack=true

+         -Dopenssl=true

          -Dgcrypt=true

          -Daudit=true

          -Delfutils=true
@@ -434,16 +512,15 @@ 

          -Dlibcryptsetup=false

  %endif

          -Delfutils=true

-         -Dpwquality=true

-         -Dqrencode=true

          -Dgnutls=true

          -Dmicrohttpd=true

          -Dlibidn2=true

-         -Dlibiptc=true

+         -Dlibiptc=false

          -Dlibcurl=true

          -Defi=true

          -Dgnu-efi=%{?have_gnu_efi:true}%{?!have_gnu_efi:false}

          -Dtpm=true

+         -Dtpm2=true

          -Dhwdb=true

          -Dsysusers=true

          -Ddefault-kill-user-processes=false
@@ -453,39 +530,107 @@ 

          -Dusers-gid=100

          -Dnobody-user=nobody

          -Dnobody-group=nobody

+         -Dcompat-mutable-uid-boundaries=true

          -Dsplit-usr=false

          -Dsplit-bin=true

+ %if %{with lto}

          -Db_lto=true

+ %else

+         -Db_lto=false

+ %endif

          -Db_ndebug=false

          -Dman=true

          -Dversion-tag=v%{version}-%{release}

+ %if 0%{?fedora}

+         -Dfallback-hostname=fedora

+ %else

+         -Dfallback-hostname=localhost

+ %endif

+         -Ddefault-dnssec=no

+         -Ddefault-dns-over-tls=opportunistic

+         # https://bugzilla.redhat.com/show_bug.cgi?id=1867830

+         -Ddefault-mdns=no

+         -Ddefault-llmnr=resolve

+         -Doomd=true

+         -Dadm-gid=4

+         -Daudio-gid=63

+         -Dcdrom-gid=11

+         -Ddialout-gid=18

+         -Ddisk-gid=6

+         -Dinput-gid=104   # https://pagure.io/setup/pull-request/27

+         -Dkmem-gid=9

+         -Dkvm-gid=36

+         -Dlp-gid=7

+         -Drender-gid=105  # https://pagure.io/setup/pull-request/27

+         -Dsgx-gid=106     # https://pagure.io/setup/pull-request/27

+         -Dtape-gid=33

+         -Dtty-gid=5

+         -Dusers-gid=100

+         -Dutmp-gid=22

+         -Dvideo-gid=39

+         -Dwheel-gid=10

+         -Dsystemd-journal-gid=190

+         -Dsystemd-network-uid=192

+         -Dsystemd-resolve-uid=193

+         # -Dsystemd-timesync-uid=, not set yet

+         # Need to set this for CentOS build

          -Ddocdir=%{_pkgdocdir}

+         # CentOS is missing newer deps required to include these

+         # But also these aren't as relevant for the hyperscale use case

+         -Dp11kit=false

+         -Duserdb=false

+         -Dhomed=false

+         -Drepart=false

+         -Dfdisk=false

+         -Dpwquality=false

+         -Dqrencode=false

+         -Dlibfido2=false

+         # Old version of PAM might not support files in /usr/lib/pam.d/ so

+         # stick with the old /etc/pam.d

+         -Dpamconfdir=/etc/pam.d

+         # Standalone binaries are only relevant on non-systemd systems

+         -Dstandalone-binaries=false

  )

  

  %if 0%{?facebook}

- %if 0%{?el7}

- %global _hierarchy legacy

- %else

- %global _hierarchy unified

- %endif

  CONFIGURE_OPTS+=(

          -Dntp-servers='1.ntp.vip.facebook.com 2.ntp.vip.facebook.com 3.ntp.vip.facebook.com 4.ntp.vip.facebook.com'

          -Ddns-servers='10.127.255.51 10.191.255.51 2401:db00:eef0:a53:: 2401:db00:eef0:b53::'

-         -Dsupport-url='https://www.facebook.com/groups/prodos.users/'

-         -Ddefault-hierarchy=%{_hierarchy}

+         -Dsupport-url='https://www.facebook.com/groups/systemd.and.friends/'

          -Dcontainer-uid-base-min=10485760

-         -Dp11kit=false

-         -Duserdb=false

-         -Dhomed=false

-         -Drepart=false

  )

  %endif

  

+ %if %{without lto}

+ %global _lto_cflags %nil

+ %endif

+ 

  export LANG=en_US.UTF-8

  export LC_ALL=en_US.UTF-8

- %meson "${CONFIGURE_OPTS[@]}"

+ # Do configuration. If doing an inplace build, try to do

+ # reconfiguration to pick up new options.

+ %if %{with inplace}

+   command -v ccache 2>/dev/null && { CC="${CC:-ccache %__cc}"; CXX="${CXX:-ccache %__cxx}"; }

+ 

+   [ -e %{_vpath_builddir}/build.ninja ] &&

+   %__meson configure %{_vpath_builddir} "${CONFIGURE_OPTS[@]}" ||

+ %endif

+ { %meson "${CONFIGURE_OPTS[@]}"; }

+ 

  %meson_build

  

+ new_triggers=%{_vpath_builddir}/src/rpm/triggers.systemd.sh

+ if ! diff -u %{SOURCE1} ${new_triggers}; then

+    echo -e "\n\n\nWARNING: triggers.systemd in Source1 is different!"

+    echo -e "      cp $PWD/${new_triggers} %{SOURCE1}\n\n\n"

+    sleep 5

+ fi

+ 

+ %if %{with selinux}

+ cd selinux

+ %{__make} -f Makefile.selinux SHARE="%{_datadir}" TARGETS="systemd_hs"

+ %endif

+ 

  %install

  export LANG=en_US.UTF-8

  export LC_ALL=en_US.UTF-8
@@ -572,8 +717,15 @@ 

  

  install -Dm0755 -t %{buildroot}%{_prefix}/lib/kernel/install.d/ %{SOURCE11}

  

+ install -Dm0644 -t %{buildroot}%{_prefix}/lib/systemd/ %{SOURCE13}

+ 

  install -D -t %{buildroot}/usr/lib/systemd/ %{SOURCE3}

  

+ # systemd-oomd default configuration

+ install -Dm0644 -t %{buildroot}%{_prefix}/lib/systemd/oomd.conf.d/ %{SOURCE14}

+ install -Dm0644 -t %{buildroot}%{system_unit_dir}/-.slice.d/ %{SOURCE15}

+ install -Dm0644 -t %{buildroot}%{system_unit_dir}/user@.service.d/ %{SOURCE16}

+ 

  sed -i 's|#!/usr/bin/env python3|#!%{__python3}|' %{buildroot}/usr/lib/systemd/tests/run-unit-tests.py

  

  install -m 0644 -D -t %{buildroot}%{_rpmconfigdir}/macros.d/ %{SOURCE21}
@@ -587,7 +739,7 @@ 

  # Split files in build root into rpms. See split-files.py for the

  # rules towards the end, anything which is an exception needs a line

  # here.

- %{__python3} %{SOURCE2} %buildroot <<EOF

+ python3 %{SOURCE2} %buildroot <<EOF

  %ghost %config(noreplace) /etc/crypttab

  %ghost /etc/udev/hwdb.bin

  /etc/inittab
@@ -596,11 +748,11 @@ 

  %ghost %config(noreplace) /etc/X11/xorg.conf.d/00-keyboard.conf

  %ghost %attr(0664,root,utmp) /run/utmp

  %ghost %attr(0664,root,utmp) /var/log/wtmp

- %ghost %attr(0600,root,utmp) /var/log/btmp

+ %ghost %attr(0660,root,utmp) /var/log/btmp

  %ghost %config(noreplace) /etc/hostname

  %ghost %config(noreplace) /etc/localtime

  %ghost %config(noreplace) /etc/locale.conf

- %ghost %config(noreplace) /etc/machine-id

+ %ghost %attr(0444,root,root) %config(noreplace) /etc/machine-id

  %ghost %config(noreplace) /etc/machine-info

  %ghost %attr(0700,root,root) %dir /var/cache/private

  %ghost %attr(0700,root,root) %dir /var/lib/private
@@ -616,11 +768,18 @@ 

  %ghost %dir /var/lib/systemd/linger

  %ghost /var/lib/systemd/random-seed

  %ghost %dir /var/lib/systemd/rfkill

- %ghost %dir /var/log/journal

+ %ghost %dir %attr(2755, root, systemd-journal) %verify(not mode) /var/log/journal

  %ghost %dir /var/log/journal/remote

  %ghost %attr(0700,root,root) %dir /var/log/private

  EOF

  

+ %if %{with selinux}

+ install -d -p %{buildroot}%{_datadir}/selinux/devel/include/contrib

+ install -p -m 0644 selinux/systemd_hs.if %{buildroot}%{_datadir}/selinux/devel/include/contrib

+ install -d -p %{buildroot}%{_datadir}/selinux/packages

+ install -p -m 0644 selinux/systemd_hs.pp.bz2 %{buildroot}%{_datadir}/selinux/packages

+ %endif

+ 

  %check

  %if %{with tests}

  export LANG=en_US.UTF-8
@@ -632,28 +791,18 @@ 

  

  %include %{SOURCE1}

  

- %pre

- getent group cdrom &>/dev/null || groupadd -r -g 11 cdrom &>/dev/null || :

- getent group utmp &>/dev/null || groupadd -r -g 22 utmp &>/dev/null || :

- getent group tape &>/dev/null || groupadd -r -g 33 tape &>/dev/null || :

- getent group dialout &>/dev/null || groupadd -r -g 18 dialout &>/dev/null || :

- getent group input &>/dev/null || groupadd -r input &>/dev/null || :

- getent group kvm &>/dev/null || groupadd -r -g 36 kvm &>/dev/null || :

- getent group render &>/dev/null || groupadd -r render &>/dev/null || :

- getent group systemd-journal &>/dev/null || groupadd -r -g 190 systemd-journal 2>&1 || :

- 

- getent group systemd-coredump &>/dev/null || groupadd -r systemd-coredump 2>&1 || :

- getent passwd systemd-coredump &>/dev/null || useradd -r -l -g systemd-coredump -d / -s /sbin/nologin -c "systemd Core Dumper" systemd-coredump &>/dev/null || :

- 

- getent group systemd-network &>/dev/null || groupadd -r -g 192 systemd-network 2>&1 || :

- getent passwd systemd-network &>/dev/null || useradd -r -u 192 -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network &>/dev/null || :

- 

- getent group systemd-resolve &>/dev/null || groupadd -r -g 193 systemd-resolve 2>&1 || :

- getent passwd systemd-resolve &>/dev/null || useradd -r -u 193 -l -g systemd-resolve -d / -s /sbin/nologin -c "systemd Resolver" systemd-resolve &>/dev/null || :

- 

  %post

  systemd-machine-id-setup &>/dev/null || :

  

+ # FIXME: move to %postun. We want to restart systemd *after* removing

+ # files from the old rpm. Right now we may still have bits the old

+ # setup if the files are not present in the new version. But before

+ # implement restarting of *other* services after the transaction, moving

+ # this would make things worse, increasing the number of warnings we get

+ # about needed daemon-reload.

+ 

+ oomd_state=$(systemctl is-active systemd-oomd 2>/dev/null || :)

+ 

  systemctl daemon-reexec &>/dev/null || {

    # systemd v239 had bug #9553 in D-Bus authentication of the private socket,

    # which was later fixed in v240 by #9625.
@@ -674,22 +823,19 @@ 

    fi

  }

  

- journalctl --update-catalog &>/dev/null || :

- systemd-tmpfiles --create &>/dev/null || :

+ if [ "$oomd_state" == "active" ]; then

+    systemctl start -q systemd-oomd 2>/dev/null || :

+ fi

+ 

+ [ $1 -eq 1 ] || exit 0

  

  # create /var/log/journal only on initial installation,

  # and only if it's writable (it won't be in rpm-ostree).

- if [ $1 -eq 1 ] && [ -w %{_localstatedir} ]; then

-     mkdir -p %{_localstatedir}/log/journal

- fi

- 

- # Make sure new journal files will be owned by the "systemd-journal" group

- machine_id=$(cat /etc/machine-id 2>/dev/null)

- chgrp systemd-journal /{run,var}/log/journal/{,${machine_id}} &>/dev/null || :

- chmod g+s /{run,var}/log/journal/{,${machine_id}} &>/dev/null || :

+ [ -w %{_localstatedir} ] && mkdir -p %{_localstatedir}/log/journal

  

- # Apply ACL to the journal directory

- setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ &>/dev/null || :

+ [ -w %{_localstatedir} ] && journalctl --update-catalog || :

+ systemd-sysusers || :

+ systemd-tmpfiles --create &>/dev/null || :

  

  # We reset the enablement of all services upon initial installation

  # https://bugzilla.redhat.com/show_bug.cgi?id=1118740#c23
@@ -698,37 +844,25 @@ 

  # https://bugzilla.redhat.com/show_bug.cgi?id=1647172.

  # We also do this for user units, see

  # https://fedoraproject.org/wiki/Changes/Systemd_presets_for_user_units.

- if [ $1 -eq 1 ] ; then

-         systemctl preset-all &>/dev/null || :

-         systemctl --global preset-all &>/dev/null || :

- fi

+ systemctl preset-all &>/dev/null || :

+ systemctl --global preset-all &>/dev/null || :

  

- %preun

- if [ $1 -eq 0 ] ; then

-         systemctl disable --quiet \

-                 remote-fs.target \

-                 getty@.service \

-                 serial-getty@.service \

-                 console-getty.service \

-                 debug-shell.service \

-                 systemd-networkd.service \

-                 systemd-networkd-wait-online.service \

-                 systemd-resolved.service \

-                 systemd-homed.service \

-                 >/dev/null || :

+ %postun

+ if [ $1 -eq 1 ]; then

+    [ -w %{_localstatedir} ] && journalctl --update-catalog || :

+    systemd-tmpfiles --create &>/dev/null || :

  fi

  

- %triggerun -- systemd < 246.1-1

- # This is for upgrades from previous versions before systemd-resolved became the default.

- systemctl --no-reload preset systemd-resolved.service &>/dev/null || :

+ %systemd_postun_with_restart systemd-timedated.service systemd-portabled.service systemd-homed.service systemd-hostnamed.service systemd-journald.service systemd-localed.service systemd-userdbd.service systemd-oomd.service

  

- if systemctl is-enabled systemd-resolved.service &>/dev/null; then

-   grep -q 'Generated by NetworkManager' /etc/resolv.conf 2>/dev/null && \

-   echo -e '/etc/resolv.conf was generated by NetworkManager.\nRemoving it to let systemd-resolved manage this file.' && \

-   mv -v /etc/resolv.conf /etc/resolv.conf.orig-with-nm || :

+ # FIXME: systemd-logind.service is excluded (https://github.com/systemd/systemd/pull/17558)

+ # FIXME: user@*.service needs to be restarted, but using systemctl --user daemon-reexec

  

-   systemctl start systemd-resolved.service &>/dev/null || :

- fi

+ %triggerpostun -- systemd < 247.3-2

+ # This is for upgrades from previous versions before oomd-defaults is available.

+ # We use %%triggerpostun here because rpm doesn't allow a second %%triggerun with

+ # a different package version.

+ systemctl --no-reload preset systemd-oomd.service &>/dev/null || :

  

  %post libs

  %{?ldconfig}
@@ -740,12 +874,6 @@ 

          sed -i.bak -r -e '

                  s/^(passwd|group):(.*)/\1:\2 systemd/

                  ' "$1" &>/dev/null || :

- 

-         # Add nss-resolve to hosts

-         grep -E -q '^hosts:.* resolve' "$1" ||

-         sed -i.bak -r -e '

-                 s/^(hosts):(.*) files( mdns4_minimal .NOTFOUND=return.)? dns myhostname/\1:\2 resolve [!UNAVAIL=return] myhostname files\3 dns/

-                 ' "$1" &>/dev/null || :

      fi

  }

  
@@ -780,10 +908,6 @@ 

  

  %global udev_services systemd-udev{d,-settle,-trigger}.service systemd-udevd-{control,kernel}.socket systemd-timesyncd.service

  

- %pre udev

- getent group systemd-timesync &>/dev/null || groupadd -r systemd-timesync 2>&1 || :

- getent passwd systemd-timesync &>/dev/null || useradd -r -l -g systemd-timesync -d / -s /sbin/nologin -c "systemd Time Synchronization" systemd-timesync &>/dev/null || :

- 

  %post udev

  # Move old stuff around in /var/lib

  mv %{_localstatedir}/lib/random-seed %{_localstatedir}/lib/systemd/random-seed &>/dev/null
@@ -798,8 +922,12 @@ 

  fi

  

  udevadm hwdb --update &>/dev/null

+ 

  %systemd_post %udev_services

- /usr/lib/systemd/systemd-random-seed save 2>&1

+ 

+ # Try to save the random seed, but don't complain if /dev/urandom is unavailable

+ /usr/lib/systemd/systemd-random-seed save 2>&1 | \

+     grep -v 'Failed to open /dev/urandom' || :

  

  # Replace obsolete keymaps

  # https://bugzilla.redhat.com/show_bug.cgi?id=1151958
@@ -810,23 +938,17 @@ 

  %systemd_preun %udev_services

  

  %postun udev

- # Only restart systemd-udev, to run the upgraded dameon.

+ # Restart some services.

  # Others are either oneshot services, or sockets, and restarting them causes issues (#1378974)

- %systemd_postun_with_restart systemd-udevd.service

- 

- %pre journal-remote

- getent group systemd-journal-remote &>/dev/null || groupadd -r systemd-journal-remote 2>&1 || :

- getent passwd systemd-journal-remote &>/dev/null || useradd -r -l -g systemd-journal-remote -d %{_localstatedir}/log/journal/remote -s /sbin/nologin -c "Journal Remote" systemd-journal-remote &>/dev/null || :

+ %systemd_postun_with_restart systemd-udevd.service systemd-timesyncd.service

  

+ %global journal_remote_units_restart systemd-journal-gatewayd.service systemd-journal-remote.service systemd-journal-upload.service

+ %global journal_remote_units_norestart systemd-journal-gatewayd.socket systemd-journal-remote.socket

  %post journal-remote

- %systemd_post systemd-journal-gatewayd.socket systemd-journal-gatewayd.service

- %systemd_post systemd-journal-remote.socket systemd-journal-remote.service

- %systemd_post systemd-journal-upload.service

+ %systemd_post %journal_remote_units_restart %journal_remote_units_norestart

  

  %preun journal-remote

- %systemd_preun systemd-journal-gatewayd.socket systemd-journal-gatewayd.service

- %systemd_preun systemd-journal-remote.socket systemd-journal-remote.service

- %systemd_preun systemd-journal-upload.service

+ %systemd_preun %journal_remote_units_restart %journal_remote_units_norestart

  if [ $1 -eq 1 ] ; then

      if [ -f %{_localstatedir}/lib/systemd/journal-upload/state -a ! -L %{_localstatedir}/lib/systemd/journal-upload ] ; then

          mkdir -p %{_localstatedir}/lib/private/systemd/journal-upload
@@ -836,9 +958,82 @@ 

  fi

  

  %postun journal-remote

- %systemd_postun_with_restart systemd-journal-gatewayd.service

- %systemd_postun_with_restart systemd-journal-remote.service

- %systemd_postun_with_restart systemd-journal-upload.service

+ %systemd_postun_with_restart %journal_remote_units_restart

+ 

+ %post networkd

+ # systemd-networkd was split out in systemd-246.6-2.

+ # Ideally, we would have a trigger scriptlet to record enablement

+ # state when upgrading from systemd <= systemd-246.6-1. But, AFAICS,

+ # rpm doesn't allow us to trigger on another package, short of

+ # querying the rpm database ourselves, which seems risky. For rpm,

+ # systemd and systemd-networkd are completely unrelated.  So let's use

+ # a hack to detect if an old systemd version is currently present in

+ # the file system.

+ # https://bugzilla.redhat.com/show_bug.cgi?id=1943263

+ if [ $1 -eq 1 ] && ls /usr/lib/systemd/libsystemd-shared-24[0-6].so &>/dev/null; then

+     echo "Skipping presets for systemd-networkd.service, seems we are upgrading from old systemd."

+ else

+     %systemd_post systemd-networkd.service systemd-networkd-wait-online.service

+ fi

+ 

+ %preun networkd

+ %systemd_preun systemd-networkd.service systemd-networkd-wait-online.service

+ 

+ %preun resolved

+ if [ $1 -eq 0 ] ; then

+         systemctl disable --quiet \

+                 systemd-resolved.service \

+                 >/dev/null || :

+ fi

+ 

+ %post resolved

+ [ $1 -gt 1 ] && exit 0

+ 

+ # Related to https://bugzilla.redhat.com/show_bug.cgi?id=1943263

+ if ls /usr/lib/systemd/libsystemd-shared-24[0-8].so &>/dev/null; then

+     echo "Skipping presets for systemd-resolved.service, seems we are upgrading from old systemd."

+     exit 0

+ fi

+ 

+ %systemd_post systemd-resolved.service

+ 

+ # Create /etc/resolv.conf symlink.

+ # We would also create it using tmpfiles, but let's do this here

+ # too before NetworkManager gets a chance. (systemd-tmpfiles invocation above

+ # does not do this, because it's marked with ! and we don't specify --boot.)

+ # https://bugzilla.redhat.com/show_bug.cgi?id=1873856

+ #

+ # If systemd is not running, don't overwrite the symlink because that

+ # will immediately break DNS resolution, since systemd-resolved is

+ # also not running (https://bugzilla.redhat.com/show_bug.cgi?id=1891847).

+ #

+ # Also don't create the symlink to the stub when the stub is disabled (#1891847 again).

+ if test -d /run/systemd/system/ &&

+    systemctl -q is-enabled systemd-resolved.service &>/dev/null &&

+    ! mountpoint /etc/resolv.conf &>/dev/null &&

+    ! systemd-analyze cat-config systemd/resolved.conf 2>/dev/null | \

+         grep -qE '^DNSStubListener\s*=\s*([nN][oO]?|[fF]|[fF][aA][lL][sS][eE]|0|[oO][fF][fF])$'; then

+   ln -fsv ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

+ fi

+ 

+ %if %{with selinux}

+ %pre selinux

+ %selinux_relabel_pre

+ 

+ %post selinux

+ %selinux_modules_install %{_datadir}/selinux/packages/systemd_hs.pp.bz2

+ %selinux_relabel_post

+ 

+ %posttrans selinux

+ %selinux_relabel_post

+ 

+ %postun selinux

+ %selinux_modules_uninstall systemd_hs

+ 

+ if [ $1 -eq 0 ]; then

+     %selinux_relabel_post

+ fi

+ %endif

  

  %global _docdir_fmt %{name}

  
@@ -870,6 +1065,8 @@ 

  

  %files rpm-macros -f .file-list-rpm-macros

  

+ %files resolved -f .file-list-resolve

+ 

  %files devel -f .file-list-devel

  

  %files udev -f .file-list-udev
@@ -878,12 +1075,332 @@ 

  

  %files journal-remote -f .file-list-remote

  

+ %files networkd -f .file-list-networkd

+ 

+ %files oomd-defaults -f .file-list-oomd-defaults

+ 

  %files tests -f .file-list-tests

  

+ %if %{with selinux}

+ %files selinux

+ %{_datadir}/selinux/devel/include/contrib/systemd_hs.if

+ %{_datadir}/selinux/packages/systemd_hs.pp.bz2

+ %endif

+ 

  %changelog

+ * Wed Nov 24 2021 Davide Cavalca <dcavalca@centosproject.org> - 249.4-2.9

+ - Disable legacy iptables support

+ 

+ * Thu Nov 11 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.8

+ - Remove revert_d219a2b07cc5dc8ffd5010f08561fab2780d8616.patch and replace with

+   proper fix (PR #21221)

+ 

+ * Wed Nov 10 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.7

+ - Add meson >= 0.57 for el8 builds. This version uses python 3.8.

+ 

+ * Wed Oct 20 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.6

+ - Revert d219a2b because it creates non-determinisitic Slice= assignments

+ 

+ * Mon Oct 11 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.5

+ - Remove duplicate Address= properties in network configs (part of PR #20892)

+ - Serialize bpf device programs across reloads/reexecs (PR #20978)

+ - Don't rewrite sysctls that are already set (PR #20676)

+ 

+ * Wed Oct 06 2021 Davide Cavalca <dcavalca@centosproject.org> - 249.4-2.4

+ - Drop qrencode-devel from BuildRequires as it's not actually used

+ 

+ * Wed Sep 29 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.3

+ - Fix to allow verifying hidden (dot) files again (PR #20875)

+ 

+ * Fri Sep 24 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.2

+ - Backport more feature support for systemd-networkd

+   (#20450, #20541, #20729, #20828)

+ 

+ * Wed Sep 22 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-2.1

+ - Sync changes from Fedora

+ - Backport one more feature for systemd-networkd (#20489)

+ 

+ * Mon Sep 20 2021 Anita Zhang <the.anitazha@gmail.com> - 249.4-1.1

+ - New stable point release

+ - Backport optimization for read_virtual_file() (#20743)

+ - Backport new features for systemd-networkd (#20743, #20472, #20477, #20484)

+ 

+ * Tue Sep 14 2021 Sahana Prasad <sahana@redhat.com>

+ - Rebuilt with OpenSSL 3.0.0

+ 

+ * Tue Aug 24 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249.4-1

+ - Latest bugfix release: various fixes for systemd-networkd,

+   systemd-resolved, systemd, systemd-boot.

+ - Backport of macros to restart systemd user units (#1993244)

+ 

+ * Fri Aug  6 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249.3-1

+ - Latest bugfix release: improved compatibility with latest glibc,

+   various small documentation fixes, and fixes for systemd-networkd bridging,

+   other minor fixes.

+ - systemctl set-property accepts glob patterns now (#1986258)

+ 

+ * Thu Jul 29 2021 Anita Zhang <the.anitazha@gmail.com> - 249.2-1.2

+ - Remove Obsoletes lines on systemd-resolved and systemd-networkd since we don't

+   want to install these by default.

+ 

+ * Wed Jul 28 2021 Anita Zhang <the.anitazha@gmail.com> - 249.2-1.1

+ - New release for 249

+ - Drop merged patches

+ - Split networkd and resolved into their own subpackages.

+ 

+ * Tue Jul 27 2021 Davide Cavalca <dcavalca@centosproject.org> - 248.5-1.3

+ - Add missing SELinux rules for the GNOME and KDE LiveDVD spins

+   (https://pagure.io/centos-sig-hyperscale/package-bugs/issue/7)

+ 

+ * Fri Jul 23 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249.2-1

+ - Latest bugfix release (a minor hwdb regression bugfix, and correction

+   to kernel commandline handling when reexecuting PID 1 in a container)

+ 

+ * Fri Jul 23 2021 Michael Catanzaro <mcatanzaro@redhat.com> - 249.2-1

+ - Build with -Ddefault-dns-over-tls=opportunistic

+   (https://fedoraproject.org/wiki/Changes/DNS_Over_TLS, #1889901)

+ 

+ * Wed Jul 21 2021 Davide Cavalca <dcavalca@centosproject.org> - 248.5-1.2

+ - Add missing SELinux rules for 248

+   (https://pagure.io/centos-sig-hyperscale/package-bugs/issue/1)

+ 

+ * Wed Jul 21 2021 Anita Zhang <anitazha@fb.com> - 248.5-1.1

+ - Update to systemd-stable 248.5 (includes fix for CVE-2021-33910)

+ 

+ * Tue Jul 20 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248.5-1

+ - Various minor documentation and correctness fixes.

+ - CVE-2021-33910, #1984020: an unchecked stack allocation could be used to

+   crash systemd and cause the system to reboot by creating a very long

+   fuse mountpoint path.

+ 

+ * Mon Jul 12 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248.4-1

+ - Assorted fixes (some systemd-resolved crashes, invalid

+   systemd-tmpfiles assertion, etc.)

+ - systemd-networkd workaround for TALOS-2020-1142, CVE-2020-13529.

+ - A big update of hardware descriptions.

+ 

+ * Wed Jul  7 2021 Neal Gompa <ngompa13@gmail.com> - 249-2

+ - Use correct NEWS URLs for systemd 249 releases in changelog entries

+ 

+ * Wed Jul  7 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249-1

+ - Latest upstream release with minor bugfixes, see

+   https://github.com/systemd/systemd/blob/v249/NEWS.

+ - systemd-oomd cpu usage is reduced (#1944646)

+ 

+ * Thu Jul  1 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249~rc3-1

+ - Latest upstream prerelease with various bugfixes, see

+   https://github.com/systemd/systemd/blob/v249-rc3/NEWS.

+ 

+ * Fri Jun 25 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249~rc2-1

+ - Latest upstream prerelease with various bugfixes, see

+   https://github.com/systemd/systemd/blob/v249-rc2/NEWS.

+ - Ignore FORCERENEW DHCP packets (TALOS-2020-1142, CVE-2020-13529, #1959398)

+ 

+ * Thu Jun 17 2021 Adam Williamson <awilliam@redhat.com> - 249~rc1-2

+ - Stop systemd providing systemd-resolved, now the subpackage exists (#1973462)

+ 

+ * Wed Jun 16 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 249~rc1-1

+ - Latest upstream prerelease, see

+   https://github.com/systemd/systemd/blob/v249-rc1/NEWS.

+   Fixes #1963428.

+ - Use systemd-sysusers to create users (#1965815)

+ - Move systemd-resolved into systemd-resolved subpackage (#1923727)

+   [patch from Petr Menšík]

+ 

+ * Mon Jun 14 2021 Anita Zhang <anitazha@fb.com> - 248.2-1.5

+ - Remove backport PR #19811 since it's still buggy

+ - Remove d586f642fd90e3bb378f7b6d3e3a64a753e51756 to fix rate limiting instead

+   (at least until sd-event rate limiting is fixed in 249).

+ 

+ * Thu Jun 10 2021 Anita Zhang <anitazha@fb.com> - 248.2-1.4

+ - Backport PR #19811 to fix issues with mount sd-event rate limiting

+ 

+ * Wed May 19 2021 Davide Cavalca <dcavalca@centosproject.org> - 248.2-1.3

+ - Add BuildRequires for python-jinja2 in preparation for 249 (see PR#19630)

+ 

+ * Mon May 17 2021 Davide Cavalca <dcavalca@centosproject.org> - 248.2-1.2

+ - Add systemd-oomd-defaults subpackage from Fedora

+ 

+ * Sat May 15 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248.3-1

+ - A fix for resolved crashes (#1946386, #1960227, #1950241)

+ - Some minor fixes for documentation, systemd-networkd, systemd-run, bootctl.

+ 

+ * Mon May 10 2021 Anita Zhang <anitazha@fb.com> - 248.2-1.1

+ - New release for 248

+ - Drop patches merged in 248.2

+ - FB only backport PR #13496 (Extend bpf cgroup program support)

+ 

+ * Fri May  7 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248.2-1

+ - Pull in some more patches from upstream (#1944646, #1885090, #1941340)

+ - Adjust modes of some %%ghost files (#1956059)

+ 

+ * Thu May  6 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248.1-1

+ - Latest stable version: a long list of minor correctness fixes all around

+   (#1955475, #911766, #1958167, #1952919)

+ - Enable tpm2-tss dependency (#1949505)

+ 

+ * Wed Apr 14 2021 Anita Zhang <anitazha@fb.com> - 247.3-10

+ - Remove systemd-resolved enablement

+ 

+ * Wed Apr  7 2021 Davide Cavalca <dcavalca@fb.com> - 247.3-9

+ - Reenable LTO now that binutils has been fixed

+ - Update FB configure options

+ 

+ * Tue Apr  6 2021 Adam Williamson <awilliam@redhat.com> - 248-2

+ - Re-enable resolved caching, we hope all major bugs are resolved now

+ 

+ * Thu Apr  1 2021 Davide Cavalca <dcavalca@fb.com> - 247.3-8

+ - Backport https://github.com/SELinuxProject/refpolicy/pull/308 to fix

+   systemd-hostnamed and systemd-localed when SELinux is enabled.

+ 

+ * Thu Apr  1 2021 Anita Zhang <anitazha@fb.com> - 247.3-7

+ - Downgrade sysv-generator warning even more (to debug)

+ 

+ * Wed Mar 31 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248-1

+ - Latest upstream release, see

+   https://github.com/systemd/systemd/blob/v248/NEWS.

+ - The changes since -rc4 are rather small, various fixes all over the place.

+   A fix to how systemd-oomd selects a candidate to kill, and more debug logging

+   to make this more transparent.

+ 

+ * Wed Mar 31 2021 Anita Zhang <anitazha@fb.com> - 247.3-6

+ - Backport PR#18621 (Ignore attempts at hidepid and subset for older kernels)

+ - Downgrade sysv-generator warning about missing native systemd unit

+ 

+ * Wed Mar 31 2021 Davide Cavalca <dcavalca@fb.com> - 247.3-5

+ - Add selinux subpackage

+ 

+ * Tue Mar 30 2021 Anita Zhang <the.anitazha@gmail.com> - 248~rc4-6

+ - Increase oomd user memory pressure limit to 50% (#1941170)

+ 

+ * Fri Mar 26 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc4-5

+ - Do not preset systemd-networkd.service and systemd-networkd-wait-online.service

+   on upgrades from before systemd-networkd was split out (#1943263)

+ - In nsswitch.conf, move nss-myhostname to the front, before nss-mdns4 (#1943199)

+ 

+ * Wed Mar 24 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc4-4

+ - Revert patch that seems to cause problems with dns resolution

+   (see comments on https://bodhi.fedoraproject.org/updates/FEDORA-2021-1c1a870ceb)

+ 

+ * Mon Mar 22 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc4-3

+ - Fix hang when processing timers during DST switch in Europe/Dublin timezone (#1941335)

+ - Fix returning combined IPv4/IPv6 responses from systemd-resolved cache (#1940715)

+   (But note that the disablement of caching added previously is

+   retained until we can do more testing.)

+ - Minor fix to interface naming by udev

+ - Fix for systemd-repart --size

+ 

+ * Fri Mar 19 2021 Adam Williamson <awilliam@redhat.com> - 248~rc4-2

+ - Disable resolved cache via config snippet (#1940715)

+ 

+ * Thu Mar 18 2021 Yu Watanabe <yuwatana@redhat.com> - 248~rc4-1

+ - Latest upstream prerelease, see

+   https://github.com/systemd/systemd/blob/v248-rc4/NEWS.

+ - A bunch of documentation updates, and correctness fixes.

+ 

+ * Wed Mar 17 2021 Anita Zhang <anitazha@fb.com> - 247.3-4

+ - Backport PR #18955 (Fixes fstab parsing)

+ - FB only backport PR #18886 (systemd-shutdown logs to /dev/console not stderr)

+ - Reenable tests by disabling LTO (work around binutils bug)

+ 

+ * Tue Mar 16 2021 Adam Williamson <awilliam@redhat.com> - 248~rc3-2

+ - Backport PR #19009 to fix CNAME redirect resolving some more (#1933433)

+ 

+ * Thu Mar 11 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc3-1

+ - Latest upstream prerelease, see

+   https://github.com/systemd/systemd/blob/v248-rc3/NEWS.

+ - A bunch of documentation updates, correctness fixes, and systemd-networkd

+   features.

+ - Resolves #1933137, #1935084, #1933873, #1931181, #1933335, #1935062, #1927148.

+ 

+ * Thu Mar 11 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc2-5

+ - Fix crash in pid1 during daemon-reexec (#1931034)

+ 

+ * Fri Mar 05 2021 Adam Williamson <awilliam@redhat.com> - 248~rc2-3

+ - Fix stub resolver CNAME chain resolving (#1933433)

+ 

+ * Mon Mar 01 2021 Josh Boyer <jwboyer@fedoraproject.org> - 248~rc2-2

+ - Don't set the fallback hostname to Fedora on non-Fedora OSes

+ 

+ * Wed Feb 24 2021 Davide Cavalca <dcavalca@fb.com> - 247.3-3

+ - Remove careinversion usage to make the package usable on older mock versions

+ 

+ * Tue Feb 23 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc2-1

+ - Latest upstream prelease, just a bunch of small fixes.

+ - Fixes #1931957.

+ 

+ * Tue Feb 23 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248~rc1-2

+ - Rebuild with the newest scriptlets

+ 

+ * Fri Feb 19 2021 Davide Cavalca <dcavalca@fb.com> - 247.3-2

+ - Disable some tests to workaround a binutils bug triggered by enabling audit

+ - Refresh patches

+ 

+ * Wed Feb 17 2021 Michel Alexandre Salim <salimma@fedoraproject.org> - 247.3-3

+ - Increase oomd user memory pressure limit to 10% (#1929856)

+ 

+ * Wed Feb 17 2021 Anita Zhang <anitazha@fb.com> - 247.3-1

+ - New release for 247

+ - Backport PR #18211 (Fixes ExecCondition= dependency bug)

+ - Backport PR #17872 (Fixes PrivateUsers=yes with other sandboxing properties)

+ - FB only backport PR #17495 (Fixes BPF pinning post-coldplug)

+ - Reenable audit support

+ 

+ * Sun Feb  7 2021 Davide Cavalca <dcavalca@fb.com> - 246.1-2

+ - Initial Hyperscale SIG package

+ - Update release to use %%dist macro

+ - Drop el7 logic

+ - Explicitly default non-FB built to the legacy hierarchy

+ - Drop no longer needed FB FusionIO patch

+ - Temporarily disable audit support while debugging a link issue

+ 

+ * Fri Feb  5 2021 Anita Zhang <the.anitazha@gmail.com> - 247.3-2

+ - Changes for https://fedoraproject.org/wiki/Changes/EnableSystemdOomd.

+ - Backports consist primarily of PR #18361, #18444, and #18401 (plus some

+   additional ones to handle merge conflicts).

+ - Create systemd-oomd-defaults subpackage to install unit drop-ins that will

+   configure systemd-oomd to monitor and act.

+ 

+ * Tue Feb  2 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247.3-1

+ - Minor stable release

+ - Fixes #1895937, #1813219, #1903106.

+ 

+ * Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org>

+ - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild

+ 

  * Mon Jan 25 2021 Anita Zhang <anitazha@fb.com> - 246.1-1.fb6

  - Backport PR #16803 to fix ConditionEnvironment=

  

+ * Wed Jan 13 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247.2-2

+ - Fix bfq patch again (#1813219)

+ 

+ * Wed Dec 23 2020 Jonathan Underwood <jonathan.underwood@gmail.com> - 247.2-2

+ - Add patch to enable crypttab to support disabling of luks read and

+   write workqueues (corresponding to

+   https://github.com/systemd/systemd/pull/18062/).

+ 

+ * Wed Dec 16 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247.2-1

+ - Minor stable release

+ - Fixes #1908071.

+ 

+ * Tue Dec  8 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247.1-3

+ - Rebuild with fallback hostname change reverted.

+ 

+ * Fri Dec  4 2020 Bastien Nocera <bnocera@redhat.com> - 247.1-2

+ - Unset fallback-hostname as plenty of applications expected localhost

+   to mean "default hostname" without ever standardising it (#1892235)

+ 

+ * Tue Dec  1 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247.1-1

+ - Latest stable release

+ - Fixes #1902819.

+ - Files to configure networking with systemd-networkd in a VM or container are

+   moved to systemd-networkd subpackage. (They were previously in the -container

+   subpackage, which is for container/VM management.)

+ 

+ * Thu Nov 26 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247-1

+ - Update to the latest version

+ - #1900878 should be fixed

+ 

  * Thu Nov 19 2020 Chris Down <cdown@fb.com> - 246.1-1.fb5

  - Updated version of PR #17495 to fix program leak

  
@@ -892,12 +1409,68 @@ 

  - Backport PR #17422 to clean up cgroups more reliably after exit

  - Backport PR #17497 to add FixedRandomDelay= support

  

+ * Tue Oct 20 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 247~rc2

+ - New upstream pre-release. See

+   https://github.com/systemd/systemd/blob/v247-rc1/NEWS.

+   Many smaller and bigger improvements and features are introduced.

+   (#1885101, #1890632, #1879216)

+ 

+   A backwards-incompatible change affects PCI network devices which

+   are connected through a bridge which is itself associated with a

+   slot. When more than one device was associated with the same slot,

+   one of the devices would pseudo-randomly get named after the slot.

+   That name is now not generated at all. This changed behaviour is

+   causes the net naming scheme to be changed to "v247". To restore

+   previous behaviour, specify net.naming-scheme=v245.

+ 

+   systemd-oomd is built, but should not be considered "production

+   ready" at this point. Testing and bug reports are welcome.

+ 

+ * Wed Sep 30 2020 Dusty Mabe <dusty@dustymabe.com> - 246.6-3

+ - Try to make files in subpackages (especially the networkd subpackage)

+   more appropriate.

+ 

+ * Thu Sep 24 2020 Filipe Brandenburger <filbranden@gmail.com> - 246.6-2

+ - Build a package with standalone binaries for non-systemd systems.

+   For now, only systemd-sysusers is included.

+ 

+ * Thu Sep 24 2020 Christian Glombek <lorbus@fedoraproject.org> - 246.6-2

+ - Split out networkd sub-package and add to main package as recommended dependency

+ 

+ * Sun Sep 20 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 246.6-1

+ - Update to latest stable release (various minor fixes: manager,

+   networking, bootct, kernel-install, systemd-dissect, systemd-homed,

+   fstab-generator, documentation) (#1876905)

+ - Do not fail in test because of kernel bug (#1803070)

+ 

  * Fri Sep 18 2020 Anita Zhang <anitazha@fb.com> - 246.1-1.fb3

  - Backport PR #16838 and #16857 to improve $PATH handling

  - Backport PR #16940 to fix ECONN handling in sockets

  - Backport PR #17031 to fix rate limiting on units in restart loop

  - Backport PR #17082 to get nspawn TTY tweaks

  

+ * Sun Sep 13 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 246.5-1

+ - Update to latest stable release (a bunch of small network-related

+   fixes in systemd-networkd and socket handling, documentation updates,

+   a bunch of fixes for error handling).

+ - Also remove existing file when creating /etc/resolv.conf symlink

+   upon installation (#1873856 again)

+ 

+ * Wed Sep  2 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 246.4-1

+ - Update to latest stable version: a rework of how the unit cache mtime works

+   (hopefully #1872068, #1871327, #1867930), plus various fixes to

+   systemd-resolved, systemd-dissect, systemd-analyze, systemd-ask-password-agent,

+   systemd-networkd, systemd-homed, systemd-machine-id-setup, presets for

+   instantiated units, documentation and shell completions.

+ - Create /etc/resolv.conf symlink upon installation (#1873856)

+ - Move nss-mdns before nss-resolve in /etc/nsswitch.conf and disable

+   mdns by default in systemd-resolved (#1867830)

+ 

+ * Wed Aug 26 2020 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 246.3-1

+ - Update to bugfix version (some networkd fixes, minor documentation

+   fixes, relax handling of various error conditions, other fixlets for

+   bugs without bugzilla numbers).

+ 

  * Tue Aug 18 2020 Anita Zhang <anitazha@fb.com> - 246.1-1.fb2

  - Gate "Obsoletes: systemd < 245.6-1" out due to dependency issues on Facebook

    systems

This is a test to see if PRs work properly now

Pull-Request has been merged by dcavalca

2 years ago
Metadata
Changes Summary 51
+5
file added
.gitignore
+1
file added
.systemd.metadata
-42
file removed
SOURCES/0001-Do-not-assert-in-test_add_acls_for_user.patch
-30
file removed
SOURCES/0001-Revert-test-path-increase-timeout.patch
-427
file removed
SOURCES/0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch
+257
file added
SOURCES/0001-rpm-don-t-specify-the-full-path-for-systemctl-and-ot.patch
+30
file added
SOURCES/0001-sysv-generator-downgrade-log-warning-about-autogener.patch
-46
file removed
SOURCES/0001-test-acl-util-output-more-debug-info.patch
-124
file removed
SOURCES/0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch
+337
file added
SOURCES/0002-rpm-use-a-helper-script-to-actually-invoke-systemctl.patch
-53
file removed
SOURCES/0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch
+35
file added
SOURCES/0003-rpm-call-needs-restart-in-parallel.patch
-234
file removed
SOURCES/0003-timer-add-new-feature-FixedRandomDelay.patch
+259
file added
SOURCES/0004-rpm-restart-user-services-at-the-end-of-the-transact.patch
+47
file added
SOURCES/0005-update-helper-also-add-user-reexec-verb.patch
+2
file added
SOURCES/10-oomd-defaults.conf
+2
file added
SOURCES/10-oomd-root-slice-defaults.conf
+3
file added
SOURCES/10-oomd-user-service-defaults.conf
-553
file removed
SOURCES/16803_fix_asserts_conditions.patch
-108
file removed
SOURCES/16838_16857_improve_path_search.patch
-317
file removed
SOURCES/16940_cleanup_socket_econn_handling.patch
-233
file removed
SOURCES/17031_propagate_start_limit_hit.patch
-316
file removed
SOURCES/17082_nspawn_tty_tweaks.patch
+90
file added
SOURCES/18621-fb.patch
+84
file added
SOURCES/18621.patch
+86
file added
SOURCES/20450.patch
+143
file added
SOURCES/20458.patch
+425
file added
SOURCES/20472.patch
+561
file added
SOURCES/20477.patch
+96
file added
SOURCES/20484.patch
+127
file added
SOURCES/20489.patch
+306
file added
SOURCES/20541.patch
+336
file added
SOURCES/20676_cherrypicked.patch
+927
file added
SOURCES/20729.patch
+41
file added
SOURCES/20743.patch
+240
file added
SOURCES/20828.patch
+26
file added
SOURCES/20875.patch
+126
file added
SOURCES/20978.patch
+172
file added
SOURCES/21221.patch
+116
file added
SOURCES/50783f91d44b1978c0e4ba62283131fac75d3745_cherrypicked.patch
-13
file removed
SOURCES/FB--Add-FusionIO-device--dev-fio-persistante-storage-udev-rule.patch
+16
file added
SOURCES/Makefile.selinux
+14
file added
SOURCES/README.build-in-place
+129
file added
SOURCES/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch
+3
file added
SOURCES/libsystemd-shared.abignore
+32 -3
file changed
SOURCES/split-files.py
+20
file added
SOURCES/systemd_hs.if
+68
file added
SOURCES/systemd_hs.te
+22 -22
file changed
SOURCES/sysusers.generate-pre.sh
+39 -61
file changed
SOURCES/triggers.systemd
+778 -205
file changed
SPECS/systemd.spec