diff options
Diffstat (limited to 'meta/recipes-core/systemd')
29 files changed, 2511 insertions, 113 deletions
diff --git a/meta/recipes-core/systemd/systemd-boot_244.3.bb b/meta/recipes-core/systemd/systemd-boot_244.5.bb index f92c639810..f92c639810 100644 --- a/meta/recipes-core/systemd/systemd-boot_244.3.bb +++ b/meta/recipes-core/systemd/systemd-boot_244.5.bb diff --git a/meta/recipes-core/systemd/systemd-conf/wired.network b/meta/recipes-core/systemd/systemd-conf/wired.network index ff807ba31f..34c20fcb24 100644 --- a/meta/recipes-core/systemd/systemd-conf/wired.network +++ b/meta/recipes-core/systemd/systemd-conf/wired.network @@ -1,6 +1,7 @@ [Match] Name=en* eth* KernelCommandLine=!nfsroot +KernelCommandLine=!ip [Network] DHCP=yes diff --git a/meta/recipes-core/systemd/systemd-conf_244.3.bb b/meta/recipes-core/systemd/systemd-conf_244.3.bb index d9ec023bfd..9b797a91f4 100644 --- a/meta/recipes-core/systemd/systemd-conf_244.3.bb +++ b/meta/recipes-core/systemd/systemd-conf_244.3.bb @@ -23,9 +23,6 @@ do_install() { # Based on change from YP bug 8141, OE commit 5196d7bacaef1076c361adaa2867be31759c1b52 do_install_append_qemuall() { install -D -m0644 ${WORKDIR}/system.conf-qemuall ${D}${systemd_unitdir}/system.conf.d/01-${PN}.conf - - # Do not install wired.network for qemu bsps - rm -rf ${D}${systemd_unitdir}/network } PACKAGE_ARCH = "${MACHINE_ARCH}" diff --git a/meta/recipes-core/systemd/systemd-serialgetty.bb b/meta/recipes-core/systemd/systemd-serialgetty.bb index 044c6c5b67..0cc0dc8c79 100644 --- a/meta/recipes-core/systemd/systemd-serialgetty.bb +++ b/meta/recipes-core/systemd/systemd-serialgetty.bb @@ -21,7 +21,7 @@ do_install() { install -d ${D}${systemd_unitdir}/system/ install -d ${D}${sysconfdir}/systemd/system/getty.target.wants/ install -m 0644 ${WORKDIR}/serial-getty@.service ${D}${systemd_unitdir}/system/ - sed -i -e s/\@BAUDRATE\@/$default_baudrate/g ${D}${systemd_unitdir}/system/serial-getty@.service + sed -i -e "s/\@BAUDRATE\@/$default_baudrate/g" ${D}${systemd_unitdir}/system/serial-getty@.service tmp="${SERIAL_CONSOLES}" for entry in $tmp ; do @@ -34,7 +34,7 @@ do_install() { else # install custom service file for the non-default baudrate install -m 0644 ${WORKDIR}/serial-getty@.service ${D}${systemd_unitdir}/system/serial-getty$baudrate@.service - sed -i -e s/\@BAUDRATE\@/$baudrate/g ${D}${systemd_unitdir}/system/serial-getty$baudrate@.service + sed -i -e "s/\@BAUDRATE\@/$baudrate/g" ${D}${systemd_unitdir}/system/serial-getty$baudrate@.service # enable the service ln -sf ${systemd_unitdir}/system/serial-getty$baudrate@.service \ ${D}${sysconfdir}/systemd/system/getty.target.wants/serial-getty$baudrate@$ttydev.service diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl index 990de1ab39..e003c860e3 100755 --- a/meta/recipes-core/systemd/systemd-systemctl/systemctl +++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl @@ -11,6 +11,7 @@ import re import sys from collections import namedtuple +from itertools import chain from pathlib import Path version = 1.0 @@ -25,12 +26,16 @@ locations = list() class SystemdFile(): """Class representing a single systemd configuration file""" - def __init__(self, root, path): + def __init__(self, root, path, instance_unit_name): self.sections = dict() self._parse(root, path) dirname = os.path.basename(path.name) + ".d" for location in locations: - for path2 in sorted((root / location / "system" / dirname).glob("*.conf")): + files = (root / location / "system" / dirname).glob("*.conf") + if instance_unit_name: + inst_dirname = instance_unit_name + ".d" + files = chain(files, (root / location / "system" / inst_dirname).glob("*.conf")) + for path2 in sorted(files): self._parse(root, path2) def _parse(self, root, path): @@ -177,12 +182,14 @@ class SystemdUnit(): raise SystemdUnitNotFoundError(self.root, unit) - def _process_deps(self, config, service, location, prop, dirstem): + def _process_deps(self, config, service, location, prop, dirstem, instance): systemdir = self.root / SYSCONFDIR / "systemd" / "system" target = ROOT / location.relative_to(self.root) try: for dependent in config.get('Install', prop): + # expand any %i to instance (ignoring escape sequence %%) + dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(instance), dependent) wants = systemdir / "{}.{}".format(dependent, dirstem) / service add_link(wants, target) @@ -193,8 +200,11 @@ class SystemdUnit(): # if we're enabling an instance, first extract the actual instance # then figure out what the template unit is template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", self.unit) + instance_unit_name = None if template: instance = template.group('instance') + if instance != "": + instance_unit_name = self.unit unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1) else: instance = None @@ -206,7 +216,7 @@ class SystemdUnit(): # ignore aliases return - config = SystemdFile(self.root, path) + config = SystemdFile(self.root, path, instance_unit_name) if instance == "": try: default_instance = config.get('Install', 'DefaultInstance')[0] @@ -219,8 +229,8 @@ class SystemdUnit(): else: service = self.unit - self._process_deps(config, service, path, 'WantedBy', 'wants') - self._process_deps(config, service, path, 'RequiredBy', 'requires') + self._process_deps(config, service, path, 'WantedBy', 'wants', instance) + self._process_deps(config, service, path, 'RequiredBy', 'requires', instance) try: for also in config.get('Install', 'Also'): diff --git a/meta/recipes-core/systemd/systemd.inc b/meta/recipes-core/systemd/systemd.inc index e73b397b5d..8b5260bb0d 100644 --- a/meta/recipes-core/systemd/systemd.inc +++ b/meta/recipes-core/systemd/systemd.inc @@ -14,8 +14,8 @@ LICENSE = "GPLv2 & LGPLv2.1" LIC_FILES_CHKSUM = "file://LICENSE.GPL2;md5=751419260aa954499f7abaabaa882bbe \ file://LICENSE.LGPL2.1;md5=4fbd65380cdd255951079008b364516c" -SRCREV = "b7ed902b2394f94e7f1fbe6c3194b5cd9a9429e6" +SRCREV = "3ceaa81c61b654ebf562464d142675bd4d57d7b6" SRCBRANCH = "v244-stable" -SRC_URI = "git://github.com/systemd/systemd-stable.git;protocol=git;branch=${SRCBRANCH}" +SRC_URI = "git://github.com/systemd/systemd-stable.git;protocol=https;branch=${SRCBRANCH}" S = "${WORKDIR}/git" diff --git a/meta/recipes-core/systemd/systemd/00-create-volatile.conf b/meta/recipes-core/systemd/systemd/00-create-volatile.conf index 87cbe1e7d3..c4277221a2 100644 --- a/meta/recipes-core/systemd/systemd/00-create-volatile.conf +++ b/meta/recipes-core/systemd/systemd/00-create-volatile.conf @@ -3,5 +3,6 @@ # inside /var/log. +d /run/lock 1777 - - - d /var/volatile/log - - - - d /var/volatile/tmp 1777 - - diff --git a/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch b/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch new file mode 100644 index 0000000000..8d3801a248 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch @@ -0,0 +1,120 @@ +From 3f9d9289ee8730a81a0464539f4e1ba2d23d0ce9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io> +Date: Tue, 3 Mar 2020 23:31:25 +0000 +Subject: [PATCH] systemd-resolved: use hostname for certificate validation in + DoT + +Widely accepted certificates for IP addresses are expensive and only +affordable for larger organizations. Therefore if the user provides +the hostname in the DNS= option, we should use it instead of the IP +address. + +(cherry picked from commit eec394f10bbfcc3d2fc8504ad8ff5be44231abd5) + +CVE: CVE-2018-21029 +Upstream-Status: Backport [ff26d281aec0877b43269f18c6282cd79a7f5529] +Signed-off-by: Marek Vasut <marex@denx.de> +--- + man/resolved.conf.xml | 16 +++++++++++----- + src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++-------- + src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++---- + 3 files changed, 34 insertions(+), 17 deletions(-) + +diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml +index 818000145b..37161ebcbc 100644 +--- a/man/resolved.conf.xml ++++ b/man/resolved.conf.xml +@@ -193,11 +193,17 @@ + <varlistentry> + <term><varname>DNSOverTLS=</varname></term> + <listitem> +- <para>Takes a boolean argument or <literal>opportunistic</literal>. +- If true all connections to the server will be encrypted. Note that +- this mode requires a DNS server that supports DNS-over-TLS and has +- a valid certificate for it's IP. If the DNS server does not support +- DNS-over-TLS all DNS requests will fail. When set to <literal>opportunistic</literal> ++ <para>Takes a boolean argument or <literal>opportunistic</literal>. If ++ true all connections to the server will be encrypted. Note that this ++ mode requires a DNS server that supports DNS-over-TLS and has a valid ++ certificate. If the hostname was specified in <varname>DNS=</varname> ++ by using the format format <literal>address#server_name</literal> it ++ is used to validate its certificate and also to enable Server Name ++ Indication (SNI) when opening a TLS connection. Otherwise ++ the certificate is checked against the server's IP. ++ If the DNS server does not support DNS-over-TLS all DNS requests will fail.</para> ++ ++ <para>When set to <literal>opportunistic</literal> + DNS request are attempted to send encrypted with DNS-over-TLS. + If the DNS server does not support TLS, DNS-over-TLS is disabled. + Note that this mode makes DNS-over-TLS vulnerable to "downgrade" +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index ed0a31e8bf..c7215723a7 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + } + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { +- stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; +- if (server->family == AF_INET) { +- stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; +- stream->dnstls_data.validation.size = 4; +- } else { +- stream->dnstls_data.validation.data = server->address.in6.s6_addr; +- stream->dnstls_data.validation.size = 16; ++ if (server->server_name) ++ gnutls_session_set_verify_cert(gs, server->server_name, 0); ++ else { ++ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; ++ if (server->family == AF_INET) { ++ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; ++ stream->dnstls_data.validation.size = 4; ++ } else { ++ stream->dnstls_data.validation.data = server->address.in6.s6_addr; ++ stream->dnstls_data.validation.size = 16; ++ } ++ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } +- gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } + + gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); +diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c +index 85e202ff74..007aedaa5b 100644 +--- a/src/resolve/resolved-dnstls-openssl.c ++++ b/src/resolve/resolved-dnstls-openssl.c +@@ -6,6 +6,7 @@ + + #include <openssl/bio.h> + #include <openssl/err.h> ++#include <openssl/x509v3.h> + + #include "io-util.h" + #include "resolved-dns-stream.h" +@@ -78,13 +79,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { + X509_VERIFY_PARAM *v; +- const unsigned char *ip; + + SSL_set_verify(s, SSL_VERIFY_PEER, NULL); + v = SSL_get0_param(s); +- ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; +- if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family))) +- return -ECONNREFUSED; ++ if (server->server_name) { ++ X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ++ if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0) ++ return -ECONNREFUSED; ++ } else { ++ const unsigned char *ip; ++ ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; ++ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) ++ return -ECONNREFUSED; ++ } + } + + ERR_clear_error(); +-- +2.40.1 + diff --git a/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch b/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch new file mode 100644 index 0000000000..6b499efbd8 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch @@ -0,0 +1,42 @@ +From 38e980a6a5a3442c2f48b1f827284388096d8ca5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Thu, 24 Jun 2021 01:22:07 +0900 +Subject: [PATCH] sd-dhcp-client: tentatively ignore FORCERENEW command + +This makes DHCP client ignore FORCERENEW requests, as unauthenticated +FORCERENEW requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). + +Let's re-enable this after RFC3118 (Authentication for DHCP Messages) +and/or RFC6704 (Forcerenew Nonce Authentication) are implemented. + +Fixes #16774. + +Upstream-Status: Backport [https://github.com/systemd/systemd/commit/38e980a6a5a3442c2f48b1f827284388096d8ca5] +CVE: CVE-2020-13529 + +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/libsystemd-network/sd-dhcp-client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/src/libsystemd-network/sd-dhcp-client.c ++++ b/src/libsystemd-network/sd-dhcp-client.c +@@ -1392,9 +1392,17 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, + if (r != DHCP_FORCERENEW) + return -ENOMSG; + ++#if 0 + log_dhcp_client(client, "FORCERENEW"); + + return 0; ++#else ++ /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP ++ * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW ++ * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */ ++ log_dhcp_client(client, "Received FORCERENEW, ignoring."); ++ return -ENOMSG; ++#endif + } + + static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { diff --git a/meta/recipes-core/systemd/systemd/CVE-2020-13776.patch b/meta/recipes-core/systemd/systemd/CVE-2020-13776.patch deleted file mode 100644 index 7b5e3e7f7a..0000000000 --- a/meta/recipes-core/systemd/systemd/CVE-2020-13776.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 156a5fd297b61bce31630d7a52c15614bf784843 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> -Date: Sun, 31 May 2020 18:21:09 +0200 -Subject: [PATCH 1/1] basic/user-util: always use base 10 for user/group - numbers - -We would parse numbers with base prefixes as user identifiers. For example, -"0x2b3bfa0" would be interpreted as UID==45334432 and "01750" would be -interpreted as UID==1000. This parsing was used also in cases where either a -user/group name or number may be specified. This means that names like -0x2b3bfa0 would be ambiguous: they are a valid user name according to our -documented relaxed rules, but they would also be parsed as numeric uids. - -This behaviour is definitely not expected by users, since tools generally only -accept decimal numbers (e.g. id, getent passwd), while other tools only accept -user names and thus will interpret such strings as user names without even -attempting to convert them to numbers (su, ssh). So let's follow suit and only -accept numbers in decimal notation. Effectively this means that we will reject -such strings as a username/uid/groupname/gid where strict mode is used, and try -to look up a user/group with such a name in relaxed mode. - -Since the function changed is fairly low-level and fairly widely used, this -affects multiple tools: loginctl show-user/enable-linger/disable-linger foo', -the third argument in sysusers.d, fourth and fifth arguments in tmpfiles.d, -etc. - -Fixes #15985. ---- - src/basic/user-util.c | 2 +- - src/test/test-user-util.c | 10 ++++++++++ - 2 files changed, 11 insertions(+), 1 deletion(-) - ---- end of commit 156a5fd297b61bce31630d7a52c15614bf784843 --- - - -Add definition of safe_atou32_full() from commit b934ac3d6e7dcad114776ef30ee9098693e7ab7e - -CVE: CVE-2020-13776 - -Upstream-Status: Backport [https://github.com/systemd/systemd.git] - -Signed-off-by: Joe Slater <joe.slater@windriver.com> - - - ---- git.orig/src/basic/user-util.c -+++ git/src/basic/user-util.c -@@ -49,7 +49,7 @@ int parse_uid(const char *s, uid_t *ret) - assert(s); - - assert_cc(sizeof(uid_t) == sizeof(uint32_t)); -- r = safe_atou32(s, &uid); -+ r = safe_atou32_full(s, 10, &uid); - if (r < 0) - return r; - ---- git.orig/src/test/test-user-util.c -+++ git/src/test/test-user-util.c -@@ -48,9 +48,19 @@ static void test_parse_uid(void) { - - r = parse_uid("65535", &uid); - assert_se(r == -ENXIO); -+ assert_se(uid == 100); -+ -+ r = parse_uid("0x1234", &uid); -+ assert_se(r == -EINVAL); -+ assert_se(uid == 100); -+ -+ r = parse_uid("01234", &uid); -+ assert_se(r == 0); -+ assert_se(uid == 1234); - - r = parse_uid("asdsdas", &uid); - assert_se(r == -EINVAL); -+ assert_se(uid == 1234); - } - - static void test_uid_ptr(void) { ---- git.orig/src/basic/parse-util.h -+++ git/src/basic/parse-util.h -@@ -45,9 +45,13 @@ static inline int safe_atoux16(const cha - - int safe_atoi16(const char *s, int16_t *ret); - --static inline int safe_atou32(const char *s, uint32_t *ret_u) { -+static inline int safe_atou32_full(const char *s, unsigned base, uint32_t *ret_u) { - assert_cc(sizeof(uint32_t) == sizeof(unsigned)); -- return safe_atou(s, (unsigned*) ret_u); -+ return safe_atou_full(s, base, (unsigned*) ret_u); -+} -+ -+static inline int safe_atou32(const char *s, uint32_t *ret_u) { -+ return safe_atou32_full(s, 0, (unsigned*) ret_u); - } - - static inline int safe_atoi32(const char *s, int32_t *ret_i) { diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch b/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch new file mode 100644 index 0000000000..e92d721d3d --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch @@ -0,0 +1,67 @@ +Backport of: + +From 441e0115646d54f080e5c3bb0ba477c892861ab9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Wed, 23 Jun 2021 11:46:41 +0200 +Subject: [PATCH 1/2] basic/unit-name: do not use strdupa() on a path + +The path may have unbounded length, for example through a fuse mount. + +CVE-2021-33910: attacked controlled alloca() leads to crash in systemd and +ultimately a kernel panic. Systemd parses the content of /proc/self/mountinfo +and each mountpoint is passed to mount_setup_unit(), which calls +unit_name_path_escape() underneath. A local attacker who is able to mount a +filesystem with a very long path can crash systemd and the whole system. + +https://bugzilla.redhat.com/show_bug.cgi?id=1970887 + +The resulting string length is bounded by UNIT_NAME_MAX, which is 256. But we +can't easily check the length after simplification before doing the +simplification, which in turns uses a copy of the string we can write to. +So we can't reject paths that are too long before doing the duplication. +Hence the most obvious solution is to switch back to strdup(), as before +7410616cd9dbbec97cf98d75324da5cda2b2f7a2. + +Upstream-Status: Backport [https://github.com/systemd/systemd/pull/20256/commits/441e0115646d54f080e5c3bb0ba477c892861ab9] +CVE: CVE-2021-33910 + +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/basic/unit-name.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -369,12 +369,13 @@ int unit_name_unescape(const char *f, char **ret) { + } + + int unit_name_path_escape(const char *f, char **ret) { +- char *p, *s; ++ _cleanup_free_ char *p = NULL; ++ char *s; + + assert(f); + assert(ret); + +- p = strdupa(f); ++ p = strdup(f); + if (!p) + return -ENOMEM; + +@@ -386,13 +387,9 @@ int unit_name_path_escape(const char *f, char **ret) { + if (!path_is_normalized(p)) + return -EINVAL; + +- /* Truncate trailing slashes */ ++ /* Truncate trailing slashes and skip leading slashes */ + delete_trailing_chars(p, "/"); +- +- /* Truncate leading slashes */ +- p = skip_leading_chars(p, "/"); +- +- s = unit_name_escape(p); ++ s = unit_name_escape(skip_leading_chars(p, "/")); + } + if (!s) + return -ENOMEM; diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch new file mode 100644 index 0000000000..341976822b --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch @@ -0,0 +1,65 @@ +Backport of the following upstream commit: +From fbb77e1e55866633c9f064e2b3bcf2b6402d962d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Tue, 23 Nov 2021 15:55:45 +0100 +Subject: [PATCH 1/3] shared/rm_rf: refactor rm_rf_children_inner() to shorten + code a bit + +CVE: CVE-2021-3997 +Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz] +Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com> +--- + src/basic/rm-rf.c | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -34,7 +34,7 @@ + const struct stat *root_dev) { + + struct stat st; +- int r; ++ int r, q = 0; + + assert(fd >= 0); + assert(fname); +@@ -50,7 +50,6 @@ + + if (is_dir) { + _cleanup_close_ int subdir_fd = -1; +- int q; + + /* if root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) +@@ -86,23 +85,15 @@ + * again for each directory */ + q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + +- r = unlinkat(fd, fname, AT_REMOVEDIR); +- if (r < 0) +- return r; +- if (q < 0) +- return q; +- +- return 1; +- +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { +- r = unlinkat(fd, fname, 0); +- if (r < 0) +- return r; +- +- return 1; +- } ++ } else if (flags & REMOVE_ONLY_DIRECTORIES) ++ return 0; + +- return 0; ++ r = unlinkat(fd, fname, is_dir ? AT_REMOVEDIR : 0); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; ++ return 1; + } + + int rm_rf_children( diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch new file mode 100644 index 0000000000..066e10fbbc --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch @@ -0,0 +1,101 @@ +Backport of the following upstream commit: +From bd0127daaaae009ade053718f7d2f297aee4acaf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Tue, 23 Nov 2021 16:56:42 +0100 +Subject: [PATCH 2/3] shared/rm_rf: refactor rm_rf() to shorten code a bit + +CVE: CVE-2021-3997 +Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz] +Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com> +--- + src/basic/rm-rf.c | 53 ++++++++++++++++++++-------------------------- + 1 file changed, 23 insertions(+), 30 deletions(-) + +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -159,7 +159,7 @@ + } + + int rm_rf(const char *path, RemoveFlags flags) { +- int fd, r; ++ int fd, r, q = 0; + + assert(path); + +@@ -191,49 +191,47 @@ + } + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (fd < 0) { ++ if (fd >= 0) { ++ /* We have a dir */ ++ r = rm_rf_children(fd, flags, NULL); ++ ++ if (FLAGS_SET(flags, REMOVE_ROOT)) { ++ q = rmdir(path); ++ if (q < 0) ++ q = -errno; ++ } ++ } else { + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) + return 0; + + if (!IN_SET(errno, ENOTDIR, ELOOP)) + return -errno; + +- if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES)) ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES) || !FLAGS_SET(flags, REMOVE_ROOT)) + return 0; + +- if (FLAGS_SET(flags, REMOVE_ROOT)) { +- +- if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { +- struct statfs s; +- +- if (statfs(path, &s) < 0) +- return -errno; +- if (is_physical_fs(&s)) +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove files from a disk file system under \"%s\", refusing.", +- path); +- } +- +- if (unlink(path) < 0) { +- if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) +- return 0; ++ if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; + ++ if (statfs(path, &s) < 0) + return -errno; +- } ++ if (is_physical_fs(&s)) ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove files from a disk file system under \"%s\", refusing.", ++ path); + } + +- return 0; ++ r = 0; ++ q = unlink(path); ++ if (q < 0) ++ q = -errno; + } + +- r = rm_rf_children(fd, flags, NULL); +- +- if (FLAGS_SET(flags, REMOVE_ROOT) && +- rmdir(path) < 0 && +- r >= 0 && +- (!FLAGS_SET(flags, REMOVE_MISSING_OK) || errno != ENOENT)) +- r = -errno; +- +- return r; ++ if (r < 0) ++ return r; ++ if (q < 0 && (q != -ENOENT || !FLAGS_SET(flags, REMOVE_MISSING_OK))) ++ return q; ++ return 0; + } + + int rm_rf_child(int fd, const char *name, RemoveFlags flags) { diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch new file mode 100644 index 0000000000..c96b8d9a6e --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch @@ -0,0 +1,266 @@ +Backport of the following upstream commit: +From bef8e8e577368697b2e6f85183b1dbc99e0e520f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Tue, 30 Nov 2021 22:29:05 +0100 +Subject: [PATCH 3/3] shared/rm-rf: loop over nested directories instead of + instead of recursing + +To remove directory structures, we need to remove the innermost items first, +and then recursively remove higher-level directories. We would recursively +descend into directories and invoke rm_rf_children and rm_rm_children_inner. +This is problematic when too many directories are nested. + +Instead, let's create a "TODO" queue. In the the queue, for each level we +hold the DIR* object we were working on, and the name of the directory. This +allows us to leave a partially-processed directory, and restart the removal +loop one level down. When done with the inner directory, we use the name to +unlinkat() it from the parent, and proceed with the removal of other items. + +Because the nesting is increased by one level, it is best to view this patch +with -b/--ignore-space-change. + +This fixes CVE-2021-3997, https://bugzilla.redhat.com/show_bug.cgi?id=2024639. +The issue was reported and patches reviewed by Qualys Team. +Mauro Matteo Cascella and Riccardo Schirone from Red Hat handled the disclosure. + +CVE: CVE-2021-3997 +Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz] +Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com> +--- + src/basic/rm-rf.c | 161 +++++++++++++++++++++++++++++++-------------- + 1 file changed, 113 insertions(+), 48 deletions(-) + +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -26,12 +26,13 @@ + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } + +-static int rm_rf_children_inner( ++static int rm_rf_inner_child( + int fd, + const char *fname, + int is_dir, + RemoveFlags flags, +- const struct stat *root_dev) { ++ const struct stat *root_dev, ++ bool allow_recursion) { + + struct stat st; + int r, q = 0; +@@ -49,9 +50,7 @@ + } + + if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; +- +- /* if root_dev is set, remove subdirectories only if device is same */ ++ /* If root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) + return 0; + +@@ -63,7 +62,6 @@ + return 0; + + if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { +- + /* This could be a subvolume, try to remove it */ + + r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +@@ -77,13 +75,16 @@ + return 1; + } + +- subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (!allow_recursion) ++ return -EISDIR; ++ ++ int subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) + return -errno; + + /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type + * again for each directory */ +- q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); ++ q = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev); + + } else if (flags & REMOVE_ONLY_DIRECTORIES) + return 0; +@@ -96,64 +97,128 @@ + return 1; + } + ++typedef struct TodoEntry { ++ DIR *dir; /* A directory that we were operating on. */ ++ char *dirname; /* The filename of that directory itself. */ ++} TodoEntry; ++ ++static void free_todo_entries(TodoEntry **todos) { ++ for (TodoEntry *x = *todos; x && x->dir; x++) { ++ closedir(x->dir); ++ free(x->dirname); ++ } ++ ++ freep(todos); ++} ++ + int rm_rf_children( + int fd, + RemoveFlags flags, + const struct stat *root_dev) { + +- _cleanup_closedir_ DIR *d = NULL; +- struct dirent *de; ++ _cleanup_(free_todo_entries) TodoEntry *todos = NULL; ++ size_t n_todo = 0, allocated = 0; ++ _cleanup_free_ char *dirname = NULL; /* Set when we are recursing and want to delete ourselves */ + int ret = 0, r; + +- assert(fd >= 0); ++ /* Return the first error we run into, but nevertheless try to go on. ++ * The passed fd is closed in all cases, including on failure. */ + +- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure. */ ++ for (;;) { /* This loop corresponds to the directory nesting level. */ ++ _cleanup_closedir_ DIR *d = NULL; ++ struct dirent *de; ++ ++ if (n_todo > 0) { ++ /* We know that we are in recursion here, because n_todo is set. ++ * We need to remove the inner directory we were operating on. */ ++ assert(dirname); ++ r = unlinkat(dirfd(todos[n_todo-1].dir), dirname, AT_REMOVEDIR); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ dirname = mfree(dirname); ++ ++ /* And now let's back out one level up */ ++ n_todo --; ++ d = TAKE_PTR(todos[n_todo].dir); ++ dirname = TAKE_PTR(todos[n_todo].dirname); ++ ++ assert(d); ++ fd = dirfd(d); /* Retrieve the file descriptor from the DIR object */ ++ assert(fd >= 0); ++ } else { ++ next_fd: ++ assert(fd >= 0); ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } ++ fd = dirfd(d); /* We donated the fd to fdopendir(). Let's make sure we sure we have ++ * the right descriptor even if it were to internally invalidate the ++ * one we passed. */ ++ ++ if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; ++ ++ if (fstatfs(fd, &sfs) < 0) ++ return -errno; ++ ++ if (is_physical_fs(&sfs)) { ++ /* We refuse to clean physical file systems with this call, unless ++ * explicitly requested. This is extra paranoia just to be sure we ++ * never ever remove non-state data. */ ++ ++ _cleanup_free_ char *path = NULL; ++ ++ (void) fd_get_path(fd, &path); ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); ++ } ++ } ++ } + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return -errno; +- } ++ FOREACH_DIRENT_ALL(de, d, return -errno) { ++ int is_dir; + +- if (!(flags & REMOVE_PHYSICAL)) { +- struct statfs sfs; ++ if (dot_or_dot_dot(de->d_name)) ++ continue; + +- if (fstatfs(dirfd(d), &sfs) < 0) +- return -errno; +- } ++ is_dir = de->d_type == DT_UNKNOWN ? -1 : de->d_type == DT_DIR; + +- if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, unless explicitly +- * requested. This is extra paranoia just to be sure we never ever remove non-state +- * data. */ +- +- _cleanup_free_ char *path = NULL; +- +- (void) fd_get_path(fd, &path); +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); +- } +- } ++ r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, false); ++ if (r == -EISDIR) { ++ /* Push the current working state onto the todo list */ + +- FOREACH_DIRENT_ALL(de, d, return -errno) { +- int is_dir; ++ if (!GREEDY_REALLOC0(todos, allocated, n_todo + 2)) ++ return log_oom(); + +- if (dot_or_dot_dot(de->d_name)) +- continue; ++ _cleanup_free_ char *newdirname = strdup(de->d_name); ++ if (!newdirname) ++ return log_oom(); + +- is_dir = +- de->d_type == DT_UNKNOWN ? -1 : +- de->d_type == DT_DIR; +- +- r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; +- } ++ int newfd = openat(fd, de->d_name, ++ O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (newfd >= 0) { ++ todos[n_todo++] = (TodoEntry) { TAKE_PTR(d), TAKE_PTR(dirname) }; ++ fd = newfd; ++ dirname = TAKE_PTR(newdirname); ++ ++ goto next_fd; + +- if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) +- ret = -errno; ++ } else if (errno != -ENOENT && ret == 0) ++ ret = -errno; ++ ++ } else if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ } ++ ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(fd) < 0 && ret >= 0) ++ ret = -errno; ++ ++ if (n_todo == 0) ++ break; ++ } + + return ret; + } +@@ -250,5 +315,5 @@ + if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) + return -EINVAL; + +- return rm_rf_children_inner(fd, name, -1, flags, NULL); ++ return rm_rf_inner_child(fd, name, -1, flags, NULL, true); + } diff --git a/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch b/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch new file mode 100644 index 0000000000..f9c6704cfc --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch @@ -0,0 +1,47 @@ +From 9102c625a673a3246d7e73d8737f3494446bad4e Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Thu, 7 Jul 2022 18:27:02 +0900 +Subject: [PATCH] time-util: fix buffer-over-run + +Fixes #23928. + +CVE: CVE-2022-3821 +Upstream-Status: Backport [https://github.com/systemd/systemd/commit/9102c625a673a3246d7e73d8737f3494446bad4e.patch] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> +Comment: Both the hunks refreshed to backport + +--- + src/basic/time-util.c | 2 +- + src/test/test-time-util.c | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/basic/time-util.c b/src/basic/time-util.c +index abbc4ad5cd70..26d59de12348 100644 +--- a/src/basic/time-util.c ++++ b/src/basic/time-util.c +@@ -514,7 +514,7 @@ char *format_timespan(char *buf, size_t + t = b; + } + +- n = MIN((size_t) k, l); ++ n = MIN((size_t) k, l-1); + + l -= n; + p += n; +diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c +index e8e4e2a67bb1..58c5fa9be40c 100644 +--- a/src/test/test-time-util.c ++++ b/src/test/test-time-util.c +@@ -501,6 +501,12 @@ int main(int argc, char *argv[]) { + test_format_timespan(1); + test_format_timespan(USEC_PER_MSEC); + test_format_timespan(USEC_PER_SEC); ++ ++ /* See issue #23928. */ ++ _cleanup_free_ char *buf; ++ assert_se(buf = new(char, 5)); ++ assert_se(buf == format_timespan(buf, 5, 100005, 1000)); ++ + test_timezone_is_valid(); + test_get_timezones(); + test_usec_add(); diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch new file mode 100644 index 0000000000..39f9480cf8 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch @@ -0,0 +1,115 @@ +From 612ebf6c913dd0e4197c44909cb3157f5c51a2f0 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering <lennart@poettering.net> +Date: Mon, 31 Aug 2020 19:37:13 +0200 +Subject: [PATCH] pager: set $LESSSECURE whenver we invoke a pager + +Some extra safety when invoked via "sudo". With this we address a +genuine design flaw of sudo, and we shouldn't need to deal with this. +But it's still a good idea to disable this surface given how exotic it +is. + +Prompted by #5666 + +CVE: CVE-2023-26604 +Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/612ebf6c913dd0e4197c44909cb3157f5c51a2f0] +Comments: Hunk not refreshed +Signed-off-by: rajmohan r <rajmohan.r@kpit.com> +--- + man/less-variables.xml | 9 +++++++++ + man/systemctl.xml | 1 + + man/systemd.xml | 1 + + src/shared/pager.c | 23 +++++++++++++++++++++-- + 4 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index 08e513c99f8e..c52511ca8e18 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -64,6 +64,15 @@ + the invoking terminal is determined to be UTF-8 compatible).</para></listitem> + </varlistentry> + ++ <varlistentry id='lesssecure'> ++ <term><varname>$SYSTEMD_LESSSECURE</varname></term> ++ ++ <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment ++ variable when invoking the pager, which controls the "secure" mode of less (which disables commands ++ such as <literal>|</literal> which allow to easily shell out to external command lines). By default ++ less secure mode is enabled, with this setting it may be disabled.</para></listitem> ++ </varlistentry> ++ + <varlistentry id='colors'> + <term><varname>$SYSTEMD_COLORS</varname></term> + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 1c5502883700..a3f0c3041a57 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -2240,6 +2240,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + <xi:include href="less-variables.xml" xpointer="pager"/> + <xi:include href="less-variables.xml" xpointer="less"/> + <xi:include href="less-variables.xml" xpointer="lesscharset"/> ++ <xi:include href="less-variables.xml" xpointer="lesssecure"/> + <xi:include href="less-variables.xml" xpointer="colors"/> + <xi:include href="less-variables.xml" xpointer="urlify"/> + </refsect1> +diff --git a/man/systemd.xml b/man/systemd.xml +index a9040545c2ab..c92cfef77689 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -692,6 +692,7 @@ + <xi:include href="less-variables.xml" xpointer="pager"/> + <xi:include href="less-variables.xml" xpointer="less"/> + <xi:include href="less-variables.xml" xpointer="lesscharset"/> ++ <xi:include href="less-variables.xml" xpointer="lesssecure"/> + <xi:include href="less-variables.xml" xpointer="colors"/> + <xi:include href="less-variables.xml" xpointer="urlify"/> + +diff --git a/src/shared/pager.c b/src/shared/pager.c +index e03be6d23b2d..9c21881241f5 100644 +--- a/src/shared/pager.c ++++ b/src/shared/pager.c +@@ -9,6 +9,7 @@ + #include <unistd.h> + + #include "copy.h" ++#include "env-util.h" + #include "fd-util.h" + #include "fileio.h" + #include "io-util.h" +@@ -152,8 +153,7 @@ int pager_open(PagerFlags flags) { + _exit(EXIT_FAILURE); + } + +- /* Initialize a good charset for less. This is +- * particularly important if we output UTF-8 ++ /* Initialize a good charset for less. This is particularly important if we output UTF-8 + * characters. */ + less_charset = getenv("SYSTEMD_LESSCHARSET"); + if (!less_charset && is_locale_utf8()) +@@ -164,6 +164,25 @@ int pager_open(PagerFlags flags) { + _exit(EXIT_FAILURE); + } + ++ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out ++ * privileged stuff. */ ++ r = getenv_bool("SYSTEMD_LESSSECURE"); ++ if (r == 0) { /* Remove env var if off */ ++ if (unsetenv("LESSSECURE") < 0) { ++ log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } else { ++ /* Set env var otherwise */ ++ if (r < 0) ++ log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ ++ if (setenv("LESSSECURE", "1", 1) < 0) { ++ log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } ++ + if (pager_args) { + r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false); + if (r < 0) { diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch new file mode 100644 index 0000000000..95da7cfad6 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch @@ -0,0 +1,264 @@ +From 1b5b507cd2d1d7a2b053151abb548475ad9c5c3b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Mon, 12 Oct 2020 18:57:32 +0200 +Subject: [PATCH] test-login: always test sd_pid_get_owner_uid(), modernize + +A long time some function only worked when in a session, and the test +didn't execute them when sd_pid_get_session() failed. Let's always call +them to increase coverage. + +While at it, let's test for ==0 not >=0 where we don't expect the function +to return anything except 0 or error. + +CVE: CVE-2023-26604 +Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/1b5b507cd2d1d7a2b053151abb548475ad9c5c3b.patch] +Comments: Hunk not refreshed +Signed-off-by: rajmohan r <rajmohan.r@kpit.com> +--- + src/libsystemd/sd-login/test-login.c | 131 ++++++++++++++------------- + 1 file changed, 70 insertions(+), 61 deletions(-) + +diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c +index c0c77e04714b..0494fc77ba18 100644 +--- a/src/libsystemd/sd-login/test-login.c ++++ b/src/libsystemd/sd-login/test-login.c +@@ -5,21 +5,22 @@ + #include "sd-login.h" + + #include "alloc-util.h" ++#include "errno-list.h" + #include "fd-util.h" + #include "format-util.h" + #include "log.h" + #include "string-util.h" + #include "strv.h" + #include "time-util.h" +-#include "util.h" ++#include "user-util.h" + + static char* format_uids(char **buf, uid_t* uids, int count) { +- int pos = 0, k, inc; ++ int pos = 0, inc; + size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1; + + assert_se(*buf = malloc(size)); + +- for (k = 0; k < count; k++) { ++ for (int k = 0; k < count; k++) { + sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc); + pos += inc; + } +@@ -30,6 +31,10 @@ static char* format_uids(char **buf, uid_t* uids, int count) { + return *buf; + } + ++static const char *e(int r) { ++ return r == 0 ? "OK" : errno_to_name(r); ++} ++ + static void test_login(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_free_ char *pp = NULL, *qq = NULL, +@@ -39,65 +44,71 @@ static void test_login(void) { + *seat = NULL, *session = NULL, + *unit = NULL, *user_unit = NULL, *slice = NULL; + int r; +- uid_t u, u2; +- char *t, **seats, **sessions; ++ uid_t u, u2 = UID_INVALID; ++ char *t, **seats = NULL, **sessions = NULL; + + r = sd_pid_get_unit(0, &unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit)); ++ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_user_unit(0, &user_unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit)); ++ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_slice(0, &slice); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice)); ++ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice)); ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ r = sd_pid_get_owner_uid(0, &u2); ++ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_session(0, &session); +- if (r < 0) { +- log_warning_errno(r, "sd_pid_get_session(0, …): %m"); +- if (r == -ENODATA) +- log_info("Seems we are not running in a session, skipping some tests."); +- } else { +- log_info("sd_pid_get_session(0, …) → \"%s\"", session); +- +- assert_se(sd_pid_get_owner_uid(0, &u2) == 0); +- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2); +- +- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0); +- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup); +- +- r = sd_uid_get_display(u2, &display_session); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"", +- u2, strnull(display_session)); +- +- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); +- sd_peer_get_session(pair[0], &pp); +- sd_peer_get_session(pair[1], &qq); +- assert_se(streq_ptr(pp, qq)); +- +- r = sd_uid_get_sessions(u2, false, &sessions); ++ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session)); ++ ++ r = sd_pid_get_cgroup(0, &cgroup); ++ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); ++ assert_se(r == 0); ++ ++ r = sd_uid_get_display(u2, &display_session); ++ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); ++ sd_peer_get_session(pair[0], &pp); ++ sd_peer_get_session(pair[1], &qq); ++ assert_se(streq_ptr(pp, qq)); ++ ++ r = sd_uid_get_sessions(u2, false, &sessions); ++ assert_se(t = strv_join(sessions, " ")); ++ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); +- assert_se(t = strv_join(sessions, " ")); +- strv_free(sessions); +- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); ++ } ++ sessions = strv_free(sessions); ++ free(t); + +- assert_se(r == sd_uid_get_sessions(u2, false, NULL)); ++ assert_se(r == sd_uid_get_sessions(u2, false, NULL)); + +- r = sd_uid_get_seats(u2, false, &seats); ++ r = sd_uid_get_seats(u2, false, &seats); ++ assert_se(t = strv_join(seats, " ")); ++ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(seats)); +- assert_se(t = strv_join(seats, " ")); +- strv_free(seats); +- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); +- +- assert_se(r == sd_uid_get_seats(u2, false, NULL)); + } ++ seats = strv_free(seats); ++ free(t); ++ ++ assert_se(r == sd_uid_get_seats(u2, false, NULL)); + + if (session) { + r = sd_session_is_active(session); +@@ -109,7 +120,7 @@ static void test_login(void) { + log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r)); + + r = sd_session_get_state(session, &state); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state); + + assert_se(sd_session_get_uid(session, &u) >= 0); +@@ -123,16 +134,16 @@ static void test_login(void) { + log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class); + + r = sd_session_get_display(session, &display); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display)); + + r = sd_session_get_remote_user(session, &remote_user); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_user(\"%s\") → \"%s\"", + session, strna(remote_user)); + + r = sd_session_get_remote_host(session, &remote_host); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_host(\"%s\") → \"%s\"", + session, strna(remote_host)); + +@@ -161,7 +172,7 @@ static void test_login(void) { + assert_se(r == -ENODATA); + } + +- assert_se(sd_uid_get_state(u, &state2) >= 0); ++ assert_se(sd_uid_get_state(u, &state2) == 0); + log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2); + } + +@@ -173,11 +184,11 @@ static void test_login(void) { + assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); + + r = sd_seat_get_active(seat, &session2, &u2); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2); + + r = sd_uid_is_on_seat(u, 1, seat); +- assert_se(r >= 0); ++ assert_se(IN_SET(r, 0, 1)); + assert_se(!!r == streq(session, session2)); + + r = sd_seat_get_sessions(seat, &sessions, &uids, &n); +@@ -185,8 +196,8 @@ static void test_login(void) { + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, " ")); + strv_free(sessions); +- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}", +- seat, r, t, n, format_uids(&buf, uids, n)); ++ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}", ++ seat, e(r), t, n, format_uids(&buf, uids, n)); + free(t); + + assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r); +@@ -204,7 +215,7 @@ static void test_login(void) { + + r = sd_seat_get_active(NULL, &t, NULL); + assert_se(IN_SET(r, 0, -ENODATA)); +- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t)); ++ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t)); + free(t); + + r = sd_get_sessions(&sessions); +@@ -244,13 +255,11 @@ static void test_login(void) { + + static void test_monitor(void) { + sd_login_monitor *m = NULL; +- unsigned n; + int r; + +- r = sd_login_monitor_new("session", &m); +- assert_se(r >= 0); ++ assert_se(sd_login_monitor_new("session", &m) == 0); + +- for (n = 0; n < 5; n++) { ++ for (unsigned n = 0; n < 5; n++) { + struct pollfd pollfd = {}; + usec_t timeout, nw; diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch new file mode 100644 index 0000000000..f02f62b772 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch @@ -0,0 +1,182 @@ +From 0a42426d797406b4b01a0d9c13bb759c2629d108 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> +Date: Wed, 7 Oct 2020 11:15:05 +0200 +Subject: [PATCH] pager: make pager secure when under euid is changed or + explicitly requested + +The variable is renamed to SYSTEMD_PAGERSECURE (because it's not just about +less now), and we automatically enable secure mode in certain cases, but not +otherwise. + +This approach is more nuanced, but should provide a better experience for +users: + +- Previusly we would set LESSSECURE=1 and trust the pager to make use of + it. But this has an effect only on less. We need to not start pagers which + are insecure when in secure mode. In particular more is like that and is a + very popular pager. + +- We don't enable secure mode always, which means that those other pagers can + reasonably used. + +- We do the right thing by default, but the user has ultimate control by + setting SYSTEMD_PAGERSECURE. + +Fixes #5666. + +v2: +- also check $PKEXEC_UID + +v3: +- use 'sd_pid_get_owner_uid() != geteuid()' as the condition + +CVE: CVE-2023-26604 +Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/0a42426d797406b4b01a0d9c13bb759c2629d108] +Comments: Hunk refreshed +Signed-off-by: rajmohan r <rajmohan.r@kpit.com> +--- + man/less-variables.xml | 30 +++++++++++++++---- + src/shared/pager.c | 63 ++++++++++++++++++++++++++------------- + 2 files changed, 66 insertions(+), 27 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index c52511c..049e9f7 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -65,12 +65,30 @@ + </varlistentry> + + <varlistentry id='lesssecure'> +- <term><varname>$SYSTEMD_LESSSECURE</varname></term> +- +- <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment +- variable when invoking the pager, which controls the "secure" mode of less (which disables commands +- such as <literal>|</literal> which allow to easily shell out to external command lines). By default +- less secure mode is enabled, with this setting it may be disabled.</para></listitem> ++ <term><varname>$SYSTEMD_PAGERSECURE</varname></term> ++ ++ <listitem><para>Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if ++ false, disabled. If <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, secure mode is enabled ++ if the effective UID is not the same as the owner of the login session, see <citerefentry ++ project='man-pages'><refentrytitle>geteuid</refentrytitle><manvolnum>2</manvolnum></citerefentry> and ++ <citerefentry><refentrytitle>sd_pid_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>. ++ In secure mode, <option>LESSSECURE=1</option> will be set when invoking the pager, and the pager shall ++ disable commands that open or create new files or start new subprocesses. When ++ <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, pagers which are not known to implement ++ secure mode will not be used. (Currently only ++ <citerefentry><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> implements ++ secure mode.)</para> ++ ++ <para>Note: when commands are invoked with elevated privileges, for example under <citerefentry ++ project='man-pages'><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry> or ++ <citerefentry ++ project='die-net'><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>, care ++ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the ++ pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname> ++ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note ++ that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be ++ honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completly ++ disable the pager using <option>--no-pager</option> instead.</para></listitem> + </varlistentry> + + <varlistentry id='colors'> +diff --git a/src/shared/pager.c b/src/shared/pager.c +index a3b6576..a72d9ea 100644 +--- a/src/shared/pager.c ++++ b/src/shared/pager.c +@@ -8,6 +8,8 @@ + #include <sys/prctl.h> + #include <unistd.h> + ++#include "sd-login.h" ++ + #include "copy.h" + #include "env-util.h" + #include "fd-util.h" +@@ -164,25 +166,42 @@ int pager_open(PagerFlags flags) { + } + + /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out +- * privileged stuff. */ +- r = getenv_bool("SYSTEMD_LESSSECURE"); +- if (r == 0) { /* Remove env var if off */ +- if (unsetenv("LESSSECURE") < 0) { +- log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } +- } else { +- /* Set env var otherwise */ ++ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the ++ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE ++ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we ++ * know to be good. */ ++ int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE"); ++ bool trust_pager = use_secure_mode >= 0; ++ if (use_secure_mode == -ENXIO) { ++ uid_t uid; ++ ++ r = sd_pid_get_owner_uid(0, &uid); + if (r < 0) +- log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); + +- if (setenv("LESSSECURE", "1", 1) < 0) { +- log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } ++ use_secure_mode = r < 0 || uid != geteuid(); ++ ++ } else if (use_secure_mode < 0) { ++ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); ++ use_secure_mode = true; + } + +- if (pager_args) { ++ /* We generally always set variables used by less, even if we end up using a different pager. ++ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */ ++ if (use_secure_mode) ++ r = setenv("LESSSECURE", "1", 1); ++ else ++ r = unsetenv("LESSSECURE"); ++ if (r < 0) { ++ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ ++ if (trust_pager && pager_args) { /* The pager config might be set globally, and we cannot ++ * know if the user adjusted it to be appropriate for the ++ * secure mode. Thus, start the pager specified through ++ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set ++ * as well. */ + r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); +@@ -194,13 +213,14 @@ int pager_open(PagerFlags flags) { + "Failed to execute '%s', using fallback pagers: %m", pager_args[0]); + } + +- /* Debian's alternatives command for pagers is +- * called 'pager'. Note that we do not call +- * sensible-pagers here, since that is just a +- * shell script that implements a logic that +- * is similar to this one anyway, but is +- * Debian-specific. */ ++ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call ++ * sensible-pagers here, since that is just a shell script that implements a logic that is ++ * similar to this one anyway, but is Debian-specific. */ + FOREACH_STRING(exe, "pager", "less", "more") { ++ /* Only less implements secure mode right now. */ ++ if (use_secure_mode && !streq(exe, "less")) ++ continue; ++ + r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); +@@ -211,6 +231,7 @@ int pager_open(PagerFlags flags) { + "Failed to execute '%s', using next fallback pager: %m", exe); + } + ++ /* Our builtin is also very secure. */ + r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in)") + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch new file mode 100644 index 0000000000..bc6b0a91c2 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch @@ -0,0 +1,32 @@ +From b8f736b30e20a2b44e7c34bb4e43b0d97ae77e3c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering <lennart@poettering.net> +Date: Thu, 15 Oct 2020 10:54:48 +0200 +Subject: [PATCH] pager: lets check SYSTEMD_PAGERSECURE with secure_getenv() + +I can't think of any real vulnerability about this, but it still feels +better to check a variable with "secure" in its name with +secure_getenv() rather than plain getenv(). + +Paranoia FTW! + +CVE: CVE-2023-26604 +Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17359/commits/b8f736b30e20a2b44e7c34bb4e43b0d97ae77e3c] +Comments: Hunk refreshed +Signed-off-by: rajmohan r <rajmohan.r@kpit.com> +--- + src/shared/pager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/pager.c b/src/shared/pager.c +index a72d9ea..250519c 100644 +--- a/src/shared/pager.c ++++ b/src/shared/pager.c +@@ -170,7 +170,7 @@ int pager_open(PagerFlags flags) { + * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE + * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we + * know to be good. */ +- int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE"); ++ int use_secure_mode = getenv_bool_secure("SYSTEMD_PAGERSECURE"); + bool trust_pager = use_secure_mode >= 0; + if (use_secure_mode == -ENXIO) { + uid_t uid; diff --git a/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch new file mode 100644 index 0000000000..86d9b0499a --- /dev/null +++ b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch @@ -0,0 +1,78 @@ +From 1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1 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 12:42:35 +0200 +Subject: [PATCH] basic: pass allocation info for ordered_set_new() and + introduce ordered_set_ensure_put() + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/basic/ordered-set.c | 21 +++++++++++++++++++++ + src/basic/ordered-set.h | 18 +++++++----------- + 2 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c +index 7fdb47e064..fb82c17b5a 100644 +--- a/src/basic/ordered-set.c ++++ b/src/basic/ordered-set.c +@@ -4,6 +4,27 @@ + #include "ordered-set.h" + #include "strv.h" + ++int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { ++ if (*s) ++ return 0; ++ ++ *s = _ordered_set_new(ops HASHMAP_DEBUG_PASS_ARGS); ++ if (!*s) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS) { ++ int r; ++ ++ r = _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_PASS_ARGS); ++ if (r < 0) ++ return r; ++ ++ return ordered_set_put(*s, p); ++} ++ + int ordered_set_consume(OrderedSet *s, void *p) { + int r; + +diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h +index a42a57eb49..2c241a808b 100644 +--- a/src/basic/ordered-set.h ++++ b/src/basic/ordered-set.h +@@ -7,20 +7,16 @@ + + typedef struct OrderedSet OrderedSet; + +-static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) { +- return (OrderedSet*) ordered_hashmap_new(ops); ++static inline OrderedSet* _ordered_set_new(const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) { ++ return (OrderedSet*) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_PASS_ARGS); + } ++#define ordered_set_new(ops) _ordered_set_new(ops HASHMAP_DEBUG_SRC_ARGS) + +-static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) { +- if (*s) +- return 0; ++int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS); ++#define ordered_set_ensure_allocated(s, ops) _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_SRC_ARGS) + +- *s = ordered_set_new(ops); +- if (!*s) +- return -ENOMEM; +- +- return 0; +-} ++int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS); ++#define ordered_set_ensure_put(s, hash_ops, key) _ordered_set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS) + + static inline OrderedSet* ordered_set_free(OrderedSet *s) { + return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s); diff --git a/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch new file mode 100644 index 0000000000..42b6e05b55 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch @@ -0,0 +1,35 @@ +From d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Mon, 26 Apr 2021 23:52:40 +0900 +Subject: [PATCH] ordered-set: introduce + ordered_set_clear/free_with_destructor() + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/basic/ordered-set.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h +index a377f20b1f..64df41766f 100644 +--- a/src/basic/ordered-set.h ++++ b/src/basic/ordered-set.h +@@ -63,6 +63,17 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s); + #define ORDERED_SET_FOREACH(e, s, i) \ + for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); ) + ++#define ordered_set_clear_with_destructor(s, f) \ ++ ({ \ ++ OrderedSet *_s = (s); \ ++ void *_item; \ ++ while ((_item = ordered_set_steal_first(_s))) \ ++ f(_item); \ ++ _s; \ ++ }) ++#define ordered_set_free_with_destructor(s, f) \ ++ ordered_set_free(ordered_set_clear_with_destructor(s, f)) ++ + DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); + DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); + diff --git a/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch new file mode 100644 index 0000000000..06c523834d --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch @@ -0,0 +1,285 @@ +From 19d9a5adf0c1a6b5a243eea0390f6f6526d569de Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Fri, 7 May 2021 15:39:16 +0900 +Subject: [PATCH] network: add skeleton of request queue + +This will be used in later commits. + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/19d9a5adf0c1a6b5a243eea0390f6f6526d569de] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/network/meson.build | 2 + + src/network/networkd-link.c | 20 +++++- + src/network/networkd-manager.c | 7 ++ + src/network/networkd-manager.h | 2 + + src/network/networkd-queue.c | 121 +++++++++++++++++++++++++++++++++ + src/network/networkd-queue.h | 42 ++++++++++++ + 6 files changed, 192 insertions(+), 2 deletions(-) + create mode 100644 src/network/networkd-queue.c + create mode 100644 src/network/networkd-queue.h + +diff --git a/src/network/meson.build b/src/network/meson.build +index 4fca3106dc..a8b9232e64 100644 +--- a/src/network/meson.build ++++ b/src/network/meson.build +@@ -105,6 +105,8 @@ sources = files(''' + networkd-network.h + networkd-nexthop.c + networkd-nexthop.h ++ networkd-queue.c ++ networkd-queue.h + networkd-route.c + networkd-route.h + networkd-routing-policy-rule.c +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 34359b2541..2f33305a27 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -30,6 +30,7 @@ + #include "networkd-manager.h" + #include "networkd-ndisc.h" + #include "networkd-neighbor.h" ++#include "networkd-queue.h" + #include "networkd-radv.h" + #include "networkd-routing-policy-rule.h" + #include "networkd-wifi.h" + +@@ -2232,6 +2244,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for + if (r < 0) + return r; + ++ link_drop_requests(link); ++ + r = link_drop_config(link); + if (r < 0) + return r; +@@ -2664,6 +2678,8 @@ static int link_carrier_lost(Link *link) { + return r; + } + ++ link_drop_requests(link); ++ + r = link_drop_config(link); + if (r < 0) + return r; +diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c +index 562ce5ca54..fd576169a9 100644 +--- a/src/network/networkd-manager.c ++++ b/src/network/networkd-manager.c +@@ -34,6 +34,7 @@ + #include "networkd-manager-bus.h" + #include "networkd-manager.h" + #include "networkd-network-bus.h" ++#include "networkd-queue.h" + #include "networkd-speed-meter.h" + #include "ordered-set.h" + #include "path-util.h" +@@ -406,6 +407,10 @@ int manager_new(Manager **ret) { + if (r < 0) + return r; + ++ r = sd_event_add_post(m->event, NULL, manager_process_requests, m); ++ if (r < 0) ++ return r; ++ + r = manager_connect_rtnl(m); + if (r < 0) + return r; +@@ -446,6 +451,8 @@ Manager* manager_free(Manager *m) { + + free(m->state_file); + ++ m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free); ++ + while ((a = hashmap_first_key(m->dhcp6_prefixes))) + (void) dhcp6_prefix_remove(m, a); + m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes); +diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h +index 301b97c1a1..26e8802871 100644 +--- a/src/network/networkd-manager.h ++++ b/src/network/networkd-manager.h +@@ -91,6 +91,8 @@ struct Manager { + usec_t speed_meter_usec_old; + + bool dhcp4_prefix_root_cannot_set_table; ++ ++ OrderedSet *request_queue; + }; + + int manager_new(Manager **ret); +diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c +new file mode 100644 +index 0000000000..24bb2c845d +--- /dev/null ++++ b/src/network/networkd-queue.c +@@ -0,0 +1,121 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++ ++#include "networkd-address.h" ++#include "networkd-manager.h" ++#include "networkd-neighbor.h" ++#include "networkd-nexthop.h" ++#include "networkd-route.h" ++#include "networkd-routing-policy-rule.h" ++#include "networkd-queue.h" ++ ++static void request_free_object(RequestType type, void *object) { ++ switch(type) { ++ default: ++ assert_not_reached("invalid request type."); ++ } ++} ++ ++Request *request_free(Request *req) { ++ if (!req) ++ return NULL; ++ ++ if (req->on_free) ++ req->on_free(req); ++ if (req->consume_object) ++ request_free_object(req->type, req->object); ++ if (req->link && req->link->manager) ++ ordered_set_remove(req->link->manager->request_queue, req); ++ link_unref(req->link); ++ ++ return mfree(req); ++} ++ ++DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free); ++ ++void request_drop(Request *req) { ++ if (req->message_counter) ++ (*req->message_counter)--; ++ ++ request_free(req); ++} ++ ++int link_queue_request( ++ Link *link, ++ RequestType type, ++ void *object, ++ bool consume_object, ++ unsigned *message_counter, ++ link_netlink_message_handler_t netlink_handler, ++ Request **ret) { ++ ++ _cleanup_(request_freep) Request *req = NULL; ++ int r; ++ ++ assert(link); ++ assert(link->manager); ++ assert(type >= 0 && type < _REQUEST_TYPE_MAX); ++ assert(object); ++ assert(netlink_handler); ++ ++ req = new(Request, 1); ++ if (!req) { ++ if (consume_object) ++ request_free_object(type, object); ++ return -ENOMEM; ++ } ++ ++ *req = (Request) { ++ .link = link, ++ .type = type, ++ .object = object, ++ .consume_object = consume_object, ++ .message_counter = message_counter, ++ .netlink_handler = netlink_handler, ++ }; ++ ++ link_ref(link); ++ ++ r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req); ++ if (r < 0) ++ return r; ++ ++ if (req->message_counter) ++ (*req->message_counter)++; ++ ++ if (ret) ++ *ret = req; ++ ++ TAKE_PTR(req); ++ return 0; ++} ++ ++int manager_process_requests(sd_event_source *s, void *userdata) { ++ Manager *manager = userdata; ++ int r; ++ ++ assert(manager); ++ ++ for (;;) { ++ bool processed = false; ++ Request *req; ++ Iterator i; ++ ORDERED_SET_FOREACH(req, manager->request_queue, i) { ++ switch(req->type) { ++ default: ++ return -EINVAL; ++ } ++ if (r < 0) ++ link_enter_failed(req->link); ++ if (r > 0) { ++ ordered_set_remove(manager->request_queue, req); ++ request_free(req); ++ processed = true; ++ } ++ } ++ ++ if (!processed) ++ break; ++ } ++ ++ return 0; ++} +diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h +new file mode 100644 +index 0000000000..4558ae548f +--- /dev/null ++++ b/src/network/networkd-queue.h +@@ -0,0 +1,42 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++#pragma once ++ ++#include "sd-event.h" ++ ++#include "networkd-link.h" ++ ++typedef struct Request Request; ++ ++typedef int (*request_after_configure_handler_t)(Request*, void*); ++typedef void (*request_on_free_handler_t)(Request*); ++ ++typedef enum RequestType { ++ _REQUEST_TYPE_MAX, ++ _REQUEST_TYPE_INVALID = -EINVAL, ++} RequestType; ++ ++typedef struct Request { ++ Link *link; ++ RequestType type; ++ bool consume_object; ++ void *object; ++ void *userdata; ++ unsigned *message_counter; ++ link_netlink_message_handler_t netlink_handler; ++ request_after_configure_handler_t after_configure; ++ request_on_free_handler_t on_free; ++} Request; ++ ++Request *request_free(Request *req); ++void request_drop(Request *req); ++ ++int link_queue_request( ++ Link *link, ++ RequestType type, ++ void *object, ++ bool consume_object, ++ unsigned *message_counter, ++ link_netlink_message_handler_t netlink_handler, ++ Request **ret); ++ ++int manager_process_requests(sd_event_source *s, void *userdata); diff --git a/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch new file mode 100644 index 0000000000..4c402e7e55 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch @@ -0,0 +1,50 @@ +From 56001f023305ea99329e27141d6e6067596491a9 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Mon, 17 May 2021 15:32:57 +0900 +Subject: [PATCH] network: also drop requests when link enters linger state + +Otherwise, if link is removed, several references to the link in remain +exist in requests. + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/56001f023305ea99329e27141d6e6067596491a9] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/network/networkd-link.c | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 67d01ac44d..b56c232eca 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -1771,6 +1771,18 @@ static void link_drop_from_master(Link *link, NetDev *netdev) { + link_unref(set_remove(master->slaves, link)); + } + ++static void link_drop_requests(Link *link) { ++ Request *req; ++ Iterator i; ++ ++ assert(link); ++ assert(link->manager); ++ ++ ORDERED_SET_FOREACH(req, link->manager->request_queue, i) ++ if (req->link == link) ++ request_drop(req); ++} ++ + void link_drop(Link *link) { + if (!link) + return; +@@ -1782,6 +1793,8 @@ void link_drop(Link *link) { + /* Drop all references from other links and manager. Note that async netlink calls may have + * references to the link, and they will be dropped when we receive replies. */ + ++ link_drop_requests(link); ++ + link_free_carrier_maps(link); + + if (link->network) { +-- +2.17.1 + diff --git a/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch new file mode 100644 index 0000000000..a186bb4095 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch @@ -0,0 +1,278 @@ +From cc2d7efc5ca09a7de4bec55e80476986839a655c Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Fri, 14 May 2021 15:58:15 +0900 +Subject: [PATCH] network: fix Link reference counter issue + +Previously, when link_new() fails, `link_unref()` was called, so, +`Manager::links` may become dirty. +This introduces `link_drop_or_unref()` and it will be called on +failure. + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/cc2d7efc5ca09a7de4bec55e80476986839a655c] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/network/networkd-link.c | 240 ++++++++++++++++++------------------ + 1 file changed, 122 insertions(+), 118 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index b56c232eca..d493afda4c 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -540,109 +540,6 @@ static int link_update_flags(Link *link, + return 0; + } + +-static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { +- _cleanup_(link_unrefp) Link *link = NULL; +- uint16_t type; +- const char *ifname, *kind = NULL; +- int r, ifindex; +- unsigned short iftype; +- +- assert(manager); +- assert(message); +- assert(ret); +- +- /* check for link kind */ +- r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); +- if (r == 0) { +- (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); +- r = sd_netlink_message_exit_container(message); +- if (r < 0) +- return r; +- } +- +- r = sd_netlink_message_get_type(message, &type); +- if (r < 0) +- return r; +- else if (type != RTM_NEWLINK) +- return -EINVAL; +- +- r = sd_rtnl_message_link_get_ifindex(message, &ifindex); +- if (r < 0) +- return r; +- else if (ifindex <= 0) +- return -EINVAL; +- +- r = sd_rtnl_message_link_get_type(message, &iftype); +- if (r < 0) +- return r; +- +- r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname); +- if (r < 0) +- return r; +- +- link = new(Link, 1); +- if (!link) +- return -ENOMEM; +- +- *link = (Link) { +- .n_ref = 1, +- .manager = manager, +- .state = LINK_STATE_PENDING, +- .ifindex = ifindex, +- .iftype = iftype, +- +- .n_dns = (unsigned) -1, +- .dns_default_route = -1, +- .llmnr = _RESOLVE_SUPPORT_INVALID, +- .mdns = _RESOLVE_SUPPORT_INVALID, +- .dnssec_mode = _DNSSEC_MODE_INVALID, +- .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, +- }; +- +- link->ifname = strdup(ifname); +- if (!link->ifname) +- return -ENOMEM; +- +- if (kind) { +- link->kind = strdup(kind); +- if (!link->kind) +- return -ENOMEM; +- } +- +- r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex); +- if (r < 0) +- log_link_debug_errno(link, r, "New device has no master, continuing without"); +- +- r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); +- if (r < 0) +- log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); +- +- if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) +- return -ENOMEM; +- +- if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) +- return -ENOMEM; +- +- if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) +- return -ENOMEM; +- +- r = hashmap_ensure_allocated(&manager->links, NULL); +- if (r < 0) +- return r; +- +- r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); +- if (r < 0) +- return r; +- +- r = link_update_flags(link, message, false); +- if (r < 0) +- return r; +- +- *ret = TAKE_PTR(link); +- +- return 0; +-} +- + void link_ntp_settings_clear(Link *link) { + link->ntp = strv_free(link->ntp); + } +@@ -2030,9 +1927,9 @@ static void link_drop_requests(Link *lin + request_drop(req); + } + +-void link_drop(Link *link) { ++Link *link_drop(Link *link) { + if (!link) +- return; ++ return NULL; + + assert(link->manager); + +@@ -2057,7 +1954,7 @@ void link_drop(Link *link) { + + /* The following must be called at last. */ + assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); +- link_unref(link); ++ return link_unref(link); + } + + static int link_joined(Link *link) { +@@ -3295,6 +3192,112 @@ ipv4ll_address_fail: + + return 0; + } ++ ++static Link *link_drop_or_unref(Link *link) { ++ if (!link) ++ return NULL; ++ if (!link->manager) ++ return link_unref(link); ++ return link_drop(link); ++} ++ ++DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref); ++ ++static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { ++ _cleanup_(link_drop_or_unrefp) Link *link = NULL; ++ uint16_t type; ++ _cleanup_free_ char *ifname = NULL, *kind = NULL; ++ int r, ifindex; ++ unsigned short iftype; ++ ++ assert(manager); ++ assert(message); ++ assert(ret); ++ ++ r = sd_netlink_message_get_type(message, &type); ++ if (r < 0) ++ return r; ++ else if (type != RTM_NEWLINK) ++ return -EINVAL; ++ ++ r = sd_rtnl_message_link_get_ifindex(message, &ifindex); ++ if (r < 0) ++ return r; ++ else if (ifindex <= 0) ++ return -EINVAL; ++ ++ r = sd_rtnl_message_link_get_type(message, &iftype); ++ if (r < 0) ++ return r; ++ ++ r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, &ifname); ++ if (r < 0) ++ return r; ++ ++ /* check for link kind */ ++ r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); ++ if (r >= 0) { ++ (void) sd_netlink_message_read_string_strdup(message, IFLA_INFO_KIND, &kind); ++ r = sd_netlink_message_exit_container(message); ++ if (r < 0) ++ return r; ++ } ++ ++ link = new(Link, 1); ++ if (!link) ++ return -ENOMEM; ++ ++ *link = (Link) { ++ .n_ref = 1, ++ .state = LINK_STATE_PENDING, ++ .ifindex = ifindex, ++ .iftype = iftype, ++ .ifname = TAKE_PTR(ifname), ++ .kind = TAKE_PTR(kind), ++ ++ .n_dns = (unsigned) -1, ++ .dns_default_route = -1, ++ .llmnr = _RESOLVE_SUPPORT_INVALID, ++ .mdns = _RESOLVE_SUPPORT_INVALID, ++ .dnssec_mode = _DNSSEC_MODE_INVALID, ++ .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID, ++ }; ++ ++ r = hashmap_ensure_allocated(&manager->links, NULL); ++ if (r < 0) ++ return r; ++ ++ r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); ++ if (r < 0) ++ return r; ++ ++ link->manager = manager; ++ ++ r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t*) &link->master_ifindex); ++ if (r < 0) ++ log_link_debug_errno(link, r, "New device has no master, continuing without"); ++ ++ r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); ++ if (r < 0) ++ log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); ++ ++ if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) ++ return -ENOMEM; ++ ++ if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) ++ return -ENOMEM; ++ ++ if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) ++ return -ENOMEM; ++ ++ r = link_update_flags(link, message, false); ++ if (r < 0) ++ return r; ++ ++ *ret = TAKE_PTR(link); ++ ++ return 0; ++} + + int link_add(Manager *m, sd_netlink_message *message, Link **ret) { + _cleanup_(sd_device_unrefp) sd_device *device = NULL; + +--- a/src/network/networkd-link.h 2021-09-02 18:04:16.900542857 +0530 ++++ b/src/network/networkd-link.h 2021-09-02 18:18:56.776571563 +0530 +@@ -175,7 +175,7 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_d + + int link_get(Manager *m, int ifindex, Link **ret); + int link_add(Manager *manager, sd_netlink_message *message, Link **ret); +-void link_drop(Link *link); ++Link *link_drop(Link *link); + + int link_down(Link *link, link_netlink_message_handler_t callback); + + diff --git a/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch new file mode 100644 index 0000000000..65bdc611df --- /dev/null +++ b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch @@ -0,0 +1,67 @@ +From 63130eb36dc51e4fd50716c585f98ebe456ca7cf Mon Sep 17 00:00:00 2001 +From: Yu Watanabe <watanabe.yu+github@gmail.com> +Date: Mon, 17 May 2021 15:40:15 +0900 +Subject: [PATCH] network: merge link_drop() and link_detach_from_manager() + +link_detach_from_manager() is only called by link_drop(). It is not +necessary to split such tiny function. + +Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/63130eb36dc51e4fd50716c585f98ebe456ca7cf] +Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com> + +--- + src/network/networkd-link.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 9d30e16b0a..67d01ac44d 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -2019,24 +2019,17 @@ static void link_drop_from_master(Link *link, NetDev *netdev) { + link_unref(set_remove(master->slaves, link)); + } + +-static void link_detach_from_manager(Link *link) { +- if (!link || !link->manager) +- return; +- +- link_unref(set_remove(link->manager->links_requesting_uuid, link)); +- link_clean(link); +- +- /* The following must be called at last. */ +- assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); +- link_unref(link); +-} +- + void link_drop(Link *link) { +- if (!link || link->state == LINK_STATE_LINGER) ++ if (!link) + return; + ++ assert(link->manager); ++ + link_set_state(link, LINK_STATE_LINGER); + ++ /* Drop all references from other links and manager. Note that async netlink calls may have ++ * references to the link, and they will be dropped when we receive replies. */ ++ + link_free_carrier_maps(link); + + if (link->network) { +@@ -2044,10 +2037,14 @@ void link_drop(Link *link) { + link_drop_from_master(link, link->network->bond); + } + +- log_link_debug(link, "Link removed"); ++ link_unref(set_remove(link->manager->links_requesting_uuid, link)); + + (void) unlink(link->state_file); +- link_detach_from_manager(link); ++ link_clean(link); ++ ++ /* The following must be called at last. */ ++ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link); ++ link_unref(link); + } + + static int link_joined(Link *link) { diff --git a/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch b/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch new file mode 100644 index 0000000000..b860da008c --- /dev/null +++ b/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch @@ -0,0 +1,35 @@ +Backport of the following upstream commit: +From bdfe7ada0d4d66e6d6e65f2822acbb1ec230f9c2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering <lennart@poettering.net> +Date: Tue, 5 Oct 2021 10:32:56 +0200 +Subject: [PATCH] rm-rf: optionally fsync() after removing directory tree + +Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz] +Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com> +--- + src/basic/rm-rf.c | 3 +++ + src/basic/rm-rf.h | 1 + + 2 files changed, 4 insertions(+) + +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -161,6 +161,9 @@ + ret = r; + } + ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) ++ ret = -errno; ++ + return ret; + } + +--- a/src/basic/rm-rf.h ++++ b/src/basic/rm-rf.h +@@ -11,6 +11,7 @@ + REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */ + REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */ + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ ++ REMOVE_SYNCFS = 1 << 7, /* syncfs() the root of the specified directory after removing everything in it */ + } RemoveFlags; + + int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev); diff --git a/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch b/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch new file mode 100644 index 0000000000..f80e6433c6 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch @@ -0,0 +1,318 @@ +Backport of the following upstream commit: +From 96906b22417c65d70933976e0ee920c70c9113a4 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering <lennart@poettering.net> +Date: Tue, 26 Jan 2021 16:30:06 +0100 +Subject: [PATCH] rm-rf: refactor rm_rf_children(), split out body of directory + iteration loop + +This splits out rm_rf_children_inner() as body of the loop. We can use +that to implement rm_rf_child() for deleting one specific entry in a +directory. + +Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz] +Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com> +--- + src/basic/rm-rf.c | 223 ++++++++++++++++++++++++++------------------- + src/basic/rm-rf.h | 3 +- + 2 files changed, 131 insertions(+), 95 deletions(-) + +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -19,138 +19,153 @@ + #include "stat-util.h" + #include "string-util.h" + ++/* We treat tmpfs/ramfs + cgroupfs as non-physical file sytems. cgroupfs is similar to tmpfs in a way after ++ * all: we can create arbitrary directory hierarchies in it, and hence can also use rm_rf() on it to remove ++ * those again. */ + static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { ++static int rm_rf_children_inner( ++ int fd, ++ const char *fname, ++ int is_dir, ++ RemoveFlags flags, ++ const struct stat *root_dev) { ++ ++ struct stat st; ++ int r; ++ ++ assert(fd >= 0); ++ assert(fname); ++ ++ if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { ++ ++ r = fstatat(fd, fname, &st, AT_SYMLINK_NOFOLLOW); ++ if (r < 0) ++ return r; ++ ++ is_dir = S_ISDIR(st.st_mode); ++ } ++ ++ if (is_dir) { ++ _cleanup_close_ int subdir_fd = -1; ++ int q; ++ ++ /* if root_dev is set, remove subdirectories only if device is same */ ++ if (root_dev && st.st_dev != root_dev->st_dev) ++ return 0; ++ ++ /* Stop at mount points */ ++ r = fd_is_mount_point(fd, fname, 0); ++ if (r < 0) ++ return r; ++ if (r > 0) ++ return 0; ++ ++ if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { ++ ++ /* This could be a subvolume, try to remove it */ ++ ++ r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); ++ if (r < 0) { ++ if (!IN_SET(r, -ENOTTY, -EINVAL)) ++ return r; ++ ++ /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ ++ } else ++ /* It was a subvolume, done. */ ++ return 1; ++ } ++ ++ subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (subdir_fd < 0) ++ return -errno; ++ ++ /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type ++ * again for each directory */ ++ q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); ++ ++ r = unlinkat(fd, fname, AT_REMOVEDIR); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; ++ ++ return 1; ++ ++ } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { ++ r = unlinkat(fd, fname, 0); ++ if (r < 0) ++ return r; ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int rm_rf_children( ++ int fd, ++ RemoveFlags flags, ++ const struct stat *root_dev) { ++ + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; + int ret = 0, r; +- struct statfs sfs; + + assert(fd >= 0); + + /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure.. */ ++ * fd, in all cases, including on failure. */ ++ ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } + + if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; + +- r = fstatfs(fd, &sfs); +- if (r < 0) { +- safe_close(fd); ++ if (fstatfs(dirfd(d), &sfs) < 0) + return -errno; + } + + if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, +- * unless explicitly requested. This is extra paranoia just +- * to be sure we never ever remove non-state data. */ ++ /* We refuse to clean physical file systems with this call, unless explicitly ++ * requested. This is extra paranoia just to be sure we never ever remove non-state ++ * data. */ ++ + _cleanup_free_ char *path = NULL; + + (void) fd_get_path(fd, &path); +- log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); +- +- safe_close(fd); +- return -EPERM; ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); + } + } + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return errno == ENOENT ? 0 : -errno; +- } +- + FOREACH_DIRENT_ALL(de, d, return -errno) { +- bool is_dir; +- struct stat st; ++ int is_dir; + + if (dot_or_dot_dot(de->d_name)) + continue; + +- if (de->d_type == DT_UNKNOWN || +- (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { +- if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- continue; +- } +- +- is_dir = S_ISDIR(st.st_mode); +- } else +- is_dir = de->d_type == DT_DIR; +- +- if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; +- +- /* if root_dev is set, remove subdirectories only if device is same */ +- if (root_dev && st.st_dev != root_dev->st_dev) +- continue; +- +- subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (subdir_fd < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- continue; +- } +- +- /* Stop at mount points */ +- r = fd_is_mount_point(fd, de->d_name, 0); +- if (r < 0) { +- if (ret == 0 && r != -ENOENT) +- ret = r; +- +- continue; +- } +- if (r > 0) +- continue; +- +- if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { +- +- /* This could be a subvolume, try to remove it */ +- +- r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +- if (r < 0) { +- if (!IN_SET(r, -ENOTTY, -EINVAL)) { +- if (ret == 0) +- ret = r; +- +- continue; +- } +- +- /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ +- } else +- /* It was a subvolume, continue. */ +- continue; +- } +- +- /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file +- * system type again for each directory */ +- r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); +- if (r < 0 && ret == 0) +- ret = r; +- +- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- } +- +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { +- +- if (unlinkat(fd, de->d_name, 0) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- } +- } ++ is_dir = ++ de->d_type == DT_UNKNOWN ? -1 : ++ de->d_type == DT_DIR; ++ ++ r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; + } ++ + return ret; + } + + int rm_rf(const char *path, RemoveFlags flags) { + int fd, r; +- struct statfs s; + + assert(path); + +@@ -195,9 +210,10 @@ + if (FLAGS_SET(flags, REMOVE_ROOT)) { + + if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; ++ + if (statfs(path, &s) < 0) + return -errno; +- + if (is_physical_fs(&s)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Attempted to remove files from a disk file system under \"%s\", refusing.", +@@ -225,3 +241,22 @@ + + return r; + } ++ ++int rm_rf_child(int fd, const char *name, RemoveFlags flags) { ++ ++ /* Removes one specific child of the specified directory */ ++ ++ if (fd < 0) ++ return -EBADF; ++ ++ if (!filename_is_valid(name)) ++ return -EINVAL; ++ ++ if ((flags & (REMOVE_ROOT|REMOVE_MISSING_OK)) != 0) /* Doesn't really make sense here, we are not supposed to remove 'fd' anyway */ ++ return -EINVAL; ++ ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) ++ return -EINVAL; ++ ++ return rm_rf_children_inner(fd, name, -1, flags, NULL); ++} +--- a/src/basic/rm-rf.h ++++ b/src/basic/rm-rf.h +@@ -13,7 +13,8 @@ + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ + } RemoveFlags; + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); ++int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev); ++int rm_rf_child(int fd, const char *name, RemoveFlags flags); + int rm_rf(const char *path, RemoveFlags flags); + + /* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */ diff --git a/meta/recipes-core/systemd/systemd/systemd-pager.sh b/meta/recipes-core/systemd/systemd/systemd-pager.sh new file mode 100644 index 0000000000..86e3e0ab78 --- /dev/null +++ b/meta/recipes-core/systemd/systemd/systemd-pager.sh @@ -0,0 +1,7 @@ +# Systemd expect a color capable pager, however the less provided +# by busybox is not. This make many interaction with systemd pretty +# annoying. As a workaround we disable the systemd pager if less +# is not the GNU version. +if ! less -V > /dev/null 2>&1 ; then + export SYSTEMD_PAGER= +fi diff --git a/meta/recipes-core/systemd/systemd_244.3.bb b/meta/recipes-core/systemd/systemd_244.5.bb index 850d64e8b0..8b2f47b92f 100644 --- a/meta/recipes-core/systemd/systemd_244.3.bb +++ b/meta/recipes-core/systemd/systemd_244.5.bb @@ -18,9 +18,28 @@ SRC_URI += "file://touchscreen.rules \ file://00-create-volatile.conf \ file://init \ file://99-default.preset \ + file://systemd-pager.sh \ file://0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch \ file://0003-implment-systemd-sysv-install-for-OE.patch \ - file://CVE-2020-13776.patch \ + file://CVE-2021-33910.patch \ + file://CVE-2020-13529.patch \ + file://basic-pass-allocation-info-for-ordered-set-new-and-introd.patch \ + file://introduce-ordered_set_clear-free-with-destructor.patch \ + file://network-add-skeleton-of-request-queue.patch \ + file://network-merge-link_drop-and-link_detach_from_manager.patch \ + file://network-also-drop-requests-when-link-enters-linger-state.patch \ + file://network-fix-Link-reference-counter-issue.patch \ + file://rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch \ + file://rm-rf-optionally-fsync-after-removing-directory-tree.patch \ + file://CVE-2018-21029.patch \ + file://CVE-2021-3997-1.patch \ + file://CVE-2021-3997-2.patch \ + file://CVE-2021-3997-3.patch \ + file://CVE-2022-3821.patch \ + file://CVE-2023-26604-1.patch \ + file://CVE-2023-26604-2.patch \ + file://CVE-2023-26604-3.patch \ + file://CVE-2023-26604-4.patch \ " # patches needed by musl @@ -50,6 +69,9 @@ SRC_URI_MUSL = "\ file://0004-src-shared-cpu-set-util.h-add-__cpu_mask-definition.patch \ " +# already applied in 244.5 +CVE_CHECK_WHITELIST += "CVE-2020-13776" + PAM_PLUGINS = " \ pam-plugin-unix \ pam-plugin-loginuid \ @@ -86,6 +108,7 @@ PACKAGECONFIG ??= " \ timesyncd \ utmp \ vconsole \ + wheel-group \ xz \ " @@ -146,6 +169,7 @@ PACKAGECONFIG[manpages] = "-Dman=true,-Dman=false,libxslt-native xmlto-native do PACKAGECONFIG[microhttpd] = "-Dmicrohttpd=true,-Dmicrohttpd=false,libmicrohttpd" PACKAGECONFIG[myhostname] = "-Dnss-myhostname=true,-Dnss-myhostname=false,,libnss-myhostname" PACKAGECONFIG[networkd] = "-Dnetworkd=true,-Dnetworkd=false" +PACKAGECONFIG[no-dns-fallback] = "-Ddns-servers=" PACKAGECONFIG[nss] = "-Dnss-systemd=true,-Dnss-systemd=false" PACKAGECONFIG[nss-mymachines] = "-Dnss-mymachines=true,-Dnss-mymachines=false" PACKAGECONFIG[nss-resolve] = "-Dnss-resolve=true,-Dnss-resolve=false" @@ -178,6 +202,7 @@ PACKAGECONFIG[sbinmerge] = "-Dsplit-bin=false,-Dsplit-bin=true" PACKAGECONFIG[utmp] = "-Dutmp=true,-Dutmp=false" PACKAGECONFIG[valgrind] = "-DVALGRIND=1,,valgrind" PACKAGECONFIG[vconsole] = "-Dvconsole=true,-Dvconsole=false,,${PN}-vconsole-setup" +PACKAGECONFIG[wheel-group] = "-Dwheel-group=true, -Dwheel-group=false" # Verify keymaps on locale change PACKAGECONFIG[xkbcommon] = "-Dxkbcommon=true,-Dxkbcommon=false,libxkbcommon" PACKAGECONFIG[xz] = "-Dxz=true,-Dxz=false,xz" @@ -195,10 +220,12 @@ rootlibexecdir = "${rootprefix}/lib" EXTRA_OEMESON += "-Dlink-udev-shared=false" EXTRA_OEMESON += "-Dnobody-user=nobody \ - -Dnobody-group=nobody \ + -Dnobody-group=nogroup \ -Drootlibdir=${rootlibdir} \ -Drootprefix=${rootprefix} \ -Ddefault-locale=C \ + -Dsystem-uid-max=999 \ + -Dsystem-gid-max=999 \ " # Hardcode target binary paths to avoid using paths from sysroot @@ -296,6 +323,9 @@ do_install() { # install default policy for presets # https://www.freedesktop.org/wiki/Software/systemd/Preset/#howto install -Dm 0644 ${WORKDIR}/99-default.preset ${D}${systemd_unitdir}/system-preset/99-default.preset + + # add a profile fragment to disable systemd pager with busybox less + install -Dm 0644 ${WORKDIR}/systemd-pager.sh ${D}${sysconfdir}/profile.d/systemd-pager.sh } python populate_packages_prepend (){ @@ -383,9 +413,9 @@ FILES_${PN}-binfmt = "${sysconfdir}/binfmt.d/ \ ${rootlibexecdir}/systemd/systemd-binfmt \ ${systemd_unitdir}/system/proc-sys-fs-binfmt_misc.* \ ${systemd_unitdir}/system/systemd-binfmt.service" -RRECOMMENDS_${PN}-binfmt = "kernel-module-binfmt-misc" +RRECOMMENDS_${PN}-binfmt = "${@bb.utils.contains('PACKAGECONFIG', 'binfmt', 'kernel-module-binfmt-misc', '', d)}" -RRECOMMENDS_${PN}-vconsole-setup = "kbd kbd-consolefonts kbd-keymaps" +RRECOMMENDS_${PN}-vconsole-setup = "${@bb.utils.contains('PACKAGECONFIG', 'vconsole', 'kbd kbd-consolefonts kbd-keymaps', '', d)}" FILES_${PN}-journal-gatewayd = "${rootlibexecdir}/systemd/systemd-journal-gatewayd \ @@ -518,6 +548,7 @@ FILES_${PN} = " ${base_bindir}/* \ ${sysconfdir}/dbus-1/ \ ${sysconfdir}/modules-load.d/ \ ${sysconfdir}/pam.d/ \ + ${sysconfdir}/profile.d/ \ ${sysconfdir}/sysctl.d/ \ ${sysconfdir}/systemd/ \ ${sysconfdir}/tmpfiles.d/ \ |