From c0e6ffa5671fad0b3830348ff960b8ec4e3d2f27 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Sun, 17 Feb 2019 13:31:37 -0500 Subject: sys-apps/systemd: backport patches for CVE-2019-6454 Bug: https://bugs.gentoo.org/677944 Package-Manager: Portage-2.3.59_p2, Repoman-2.3.12_p67 Signed-off-by: Mike Gilbert --- ...-message-paths-longer-than-BUS_PATH_SIZE_.patch | 48 +++ ...mporary-strings-to-hold-dbus-paths-on-the.patch | 188 +++++++++ ...e-receive-an-invalid-dbus-message-ignore-.patch | 54 +++ sys-apps/systemd/systemd-241-r1.ebuild | 461 +++++++++++++++++++++ 4 files changed, 751 insertions(+) create mode 100644 sys-apps/systemd/files/CVE-2019-6454/0001-Refuse-dbus-message-paths-longer-than-BUS_PATH_SIZE_.patch create mode 100644 sys-apps/systemd/files/CVE-2019-6454/0002-Allocate-temporary-strings-to-hold-dbus-paths-on-the.patch create mode 100644 sys-apps/systemd/files/CVE-2019-6454/0003-sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch create mode 100644 sys-apps/systemd/systemd-241-r1.ebuild (limited to 'sys-apps/systemd') diff --git a/sys-apps/systemd/files/CVE-2019-6454/0001-Refuse-dbus-message-paths-longer-than-BUS_PATH_SIZE_.patch b/sys-apps/systemd/files/CVE-2019-6454/0001-Refuse-dbus-message-paths-longer-than-BUS_PATH_SIZE_.patch new file mode 100644 index 000000000000..6a0c8d1b0c51 --- /dev/null +++ b/sys-apps/systemd/files/CVE-2019-6454/0001-Refuse-dbus-message-paths-longer-than-BUS_PATH_SIZE_.patch @@ -0,0 +1,48 @@ +From 29de632674473729d1e9497b6fe47e7c88682ed9 Mon Sep 17 00:00:00 2001 +From: Riccardo Schirone +Date: Mon, 4 Feb 2019 14:29:09 +0100 +Subject: [PATCH 1/3] Refuse dbus message paths longer than BUS_PATH_SIZE_MAX + limit. + +Even though the dbus specification does not enforce any length limit on the +path of a dbus message, having to analyze too long strings in PID1 may be +time-consuming and it may have security impacts. + +In any case, the limit is set so high that real-life applications should not +have a problem with it. +--- + src/libsystemd/sd-bus/bus-internal.c | 2 +- + src/libsystemd/sd-bus/bus-internal.h | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.c b/src/libsystemd/sd-bus/bus-internal.c +index 40acae2133..598b7f110c 100644 +--- a/src/libsystemd/sd-bus/bus-internal.c ++++ b/src/libsystemd/sd-bus/bus-internal.c +@@ -43,7 +43,7 @@ bool object_path_is_valid(const char *p) { + if (slash) + return false; + +- return true; ++ return (q - p) <= BUS_PATH_SIZE_MAX; + } + + char* object_path_startswith(const char *a, const char *b) { +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index f208b294d8..a8d61bf72a 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -332,6 +332,10 @@ struct sd_bus { + + #define BUS_MESSAGE_SIZE_MAX (128*1024*1024) + #define BUS_AUTH_SIZE_MAX (64*1024) ++/* Note that the D-Bus specification states that bus paths shall have no size limit. We enforce here one ++ * anyway, since truly unbounded strings are a security problem. The limit we pick is relatively large however, ++ * to not clash unnecessarily with real-life applications. */ ++#define BUS_PATH_SIZE_MAX (64*1024) + + #define BUS_CONTAINER_DEPTH 128 + +-- +2.20.1 + diff --git a/sys-apps/systemd/files/CVE-2019-6454/0002-Allocate-temporary-strings-to-hold-dbus-paths-on-the.patch b/sys-apps/systemd/files/CVE-2019-6454/0002-Allocate-temporary-strings-to-hold-dbus-paths-on-the.patch new file mode 100644 index 000000000000..bbc6db974d4a --- /dev/null +++ b/sys-apps/systemd/files/CVE-2019-6454/0002-Allocate-temporary-strings-to-hold-dbus-paths-on-the.patch @@ -0,0 +1,188 @@ +From 1ffe59592c5cbf924eb81a3662b4252ba6de7132 Mon Sep 17 00:00:00 2001 +From: Riccardo Schirone +Date: Mon, 4 Feb 2019 14:29:28 +0100 +Subject: [PATCH 2/3] Allocate temporary strings to hold dbus paths on the heap + +Paths are limited to BUS_PATH_SIZE_MAX but the maximum size is anyway too big +to be allocated on the stack, so let's switch to the heap where there is a +clear way to understand if the allocation fails. +--- + src/libsystemd/sd-bus/bus-objects.c | 68 +++++++++++++++++++++++------ + 1 file changed, 54 insertions(+), 14 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-objects.c b/src/libsystemd/sd-bus/bus-objects.c +index 58329f3fe7..54b977418e 100644 +--- a/src/libsystemd/sd-bus/bus-objects.c ++++ b/src/libsystemd/sd-bus/bus-objects.c +@@ -1133,7 +1133,8 @@ static int object_manager_serialize_path_and_fallbacks( + const char *path, + sd_bus_error *error) { + +- char *prefix; ++ _cleanup_free_ char *prefix = NULL; ++ size_t pl; + int r; + + assert(bus); +@@ -1149,7 +1150,12 @@ static int object_manager_serialize_path_and_fallbacks( + return 0; + + /* Second, add fallback vtables registered for any of the prefixes */ +- prefix = newa(char, strlen(path) + 1); ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; ++ + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_manager_serialize_path(bus, reply, prefix, path, true, error); + if (r < 0) +@@ -1345,6 +1351,7 @@ static int object_find_and_run( + } + + int bus_process_object(sd_bus *bus, sd_bus_message *m) { ++ _cleanup_free_ char *prefix = NULL; + int r; + size_t pl; + bool found_object = false; +@@ -1369,9 +1376,12 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) { + assert(m->member); + + pl = strlen(m->path); +- do { +- char prefix[pl+1]; ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; + ++ do { + bus->nodes_modified = false; + + r = object_find_and_run(bus, m, m->path, false, &found_object); +@@ -1498,9 +1508,15 @@ static int bus_find_parent_object_manager(sd_bus *bus, struct node **out, const + + n = hashmap_get(bus->nodes, path); + if (!n) { +- char *prefix; ++ _cleanup_free_ char *prefix = NULL; ++ size_t pl; ++ ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; + +- prefix = newa(char, strlen(path) + 1); + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + n = hashmap_get(bus->nodes, prefix); + if (n) +@@ -2083,8 +2099,9 @@ _public_ int sd_bus_emit_properties_changed_strv( + const char *interface, + char **names) { + ++ _cleanup_free_ char *prefix = NULL; + bool found_interface = false; +- char *prefix; ++ size_t pl; + int r; + + assert_return(bus, -EINVAL); +@@ -2105,6 +2122,12 @@ _public_ int sd_bus_emit_properties_changed_strv( + + BUS_DONT_DESTROY(bus); + ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; ++ + do { + bus->nodes_modified = false; + +@@ -2114,7 +2137,6 @@ _public_ int sd_bus_emit_properties_changed_strv( + if (bus->nodes_modified) + continue; + +- prefix = newa(char, strlen(path) + 1); + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names); + if (r != 0) +@@ -2246,7 +2268,8 @@ static int object_added_append_all_prefix( + + static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { + _cleanup_set_free_ Set *s = NULL; +- char *prefix; ++ _cleanup_free_ char *prefix = NULL; ++ size_t pl; + int r; + + assert(bus); +@@ -2291,7 +2314,12 @@ static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *p + if (bus->nodes_modified) + return 0; + +- prefix = newa(char, strlen(path) + 1); ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; ++ + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_added_append_all_prefix(bus, m, s, prefix, path, true); + if (r < 0) +@@ -2430,7 +2458,8 @@ static int object_removed_append_all_prefix( + + static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) { + _cleanup_set_free_ Set *s = NULL; +- char *prefix; ++ _cleanup_free_ char *prefix = NULL; ++ size_t pl; + int r; + + assert(bus); +@@ -2462,7 +2491,12 @@ static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char + if (bus->nodes_modified) + return 0; + +- prefix = newa(char, strlen(path) + 1); ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; ++ + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = object_removed_append_all_prefix(bus, m, s, prefix, path, true); + if (r < 0) +@@ -2612,7 +2646,8 @@ static int interfaces_added_append_one( + const char *path, + const char *interface) { + +- char *prefix; ++ _cleanup_free_ char *prefix = NULL; ++ size_t pl; + int r; + + assert(bus); +@@ -2626,7 +2661,12 @@ static int interfaces_added_append_one( + if (bus->nodes_modified) + return 0; + +- prefix = newa(char, strlen(path) + 1); ++ pl = strlen(path); ++ assert(pl <= BUS_PATH_SIZE_MAX); ++ prefix = new(char, pl + 1); ++ if (!prefix) ++ return -ENOMEM; ++ + OBJECT_PATH_FOREACH_PREFIX(prefix, path) { + r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true); + if (r != 0) +-- +2.20.1 + diff --git a/sys-apps/systemd/files/CVE-2019-6454/0003-sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch b/sys-apps/systemd/files/CVE-2019-6454/0003-sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch new file mode 100644 index 000000000000..cc03893a588d --- /dev/null +++ b/sys-apps/systemd/files/CVE-2019-6454/0003-sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch @@ -0,0 +1,54 @@ +From 8d3cea620ab661897fb485ece7332a9073c1783d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 13 Feb 2019 16:51:22 +0100 +Subject: [PATCH 3/3] sd-bus: if we receive an invalid dbus message, ignore and + proceeed + +dbus-daemon might have a slightly different idea of what a valid msg is +than us (for example regarding valid msg and field sizes). Let's hence +try to proceed if we can and thus drop messages rather than fail the +connection if we fail to validate a message. + +Hopefully the differences in what is considered valid are not visible +for real-life usecases, but are specific to exploit attempts only. +--- + src/libsystemd/sd-bus/bus-socket.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c +index 30d6455b6f..441b4a816f 100644 +--- a/src/libsystemd/sd-bus/bus-socket.c ++++ b/src/libsystemd/sd-bus/bus-socket.c +@@ -1072,7 +1072,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) { + } + + static int bus_socket_make_message(sd_bus *bus, size_t size) { +- sd_bus_message *t; ++ sd_bus_message *t = NULL; + void *b; + int r; + +@@ -1097,7 +1097,9 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { + bus->fds, bus->n_fds, + NULL, + &t); +- if (r < 0) { ++ if (r == -EBADMSG) ++ log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description)); ++ else if (r < 0) { + free(b); + return r; + } +@@ -1108,7 +1110,8 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { + bus->fds = NULL; + bus->n_fds = 0; + +- bus->rqueue[bus->rqueue_size++] = t; ++ if (t) ++ bus->rqueue[bus->rqueue_size++] = t; + + return 1; + } +-- +2.20.1 + diff --git a/sys-apps/systemd/systemd-241-r1.ebuild b/sys-apps/systemd/systemd-241-r1.ebuild new file mode 100644 index 000000000000..47f33c6fcff7 --- /dev/null +++ b/sys-apps/systemd/systemd-241-r1.ebuild @@ -0,0 +1,461 @@ +# Copyright 2011-2019 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=7 + +if [[ ${PV} == 9999 ]]; then + EGIT_REPO_URI="https://github.com/systemd/systemd.git" + inherit git-r3 +else + MY_PV=${PV/_/-} + MY_P=${PN}-${MY_PV} + S=${WORKDIR}/${MY_P} + SRC_URI="https://github.com/systemd/systemd/archive/v${MY_PV}/${MY_P}.tar.gz" + KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sparc ~x86" +fi + +PYTHON_COMPAT=( python{3_5,3_6,3_7} ) + +inherit bash-completion-r1 linux-info meson multilib-minimal ninja-utils pam python-any-r1 systemd toolchain-funcs udev user + +DESCRIPTION="System and service manager for Linux" +HOMEPAGE="https://www.freedesktop.org/wiki/Software/systemd" + +LICENSE="GPL-2 LGPL-2.1 MIT public-domain" +SLOT="0/2" +IUSE="acl apparmor audit build cryptsetup curl elfutils +gcrypt gnuefi http idn importd +kmod libidn2 +lz4 lzma nat pam pcre policykit qrcode +resolvconf +seccomp selinux +split-usr ssl +sysv-utils test vanilla xkb" + +REQUIRED_USE="importd? ( curl gcrypt lzma )" +RESTRICT="!test? ( test )" + +MINKV="3.11" + +COMMON_DEPEND=">=sys-apps/util-linux-2.30:0=[${MULTILIB_USEDEP}] + sys-libs/libcap:0=[${MULTILIB_USEDEP}] + !=sys-process/audit-2:0= ) + cryptsetup? ( >=sys-fs/cryptsetup-1.6:0= ) + curl? ( net-misc/curl:0= ) + elfutils? ( >=dev-libs/elfutils-0.158:0= ) + gcrypt? ( >=dev-libs/libgcrypt-1.4.5:0=[${MULTILIB_USEDEP}] ) + http? ( + >=net-libs/libmicrohttpd-0.9.33:0= + ssl? ( >=net-libs/gnutls-3.1.4:0= ) + ) + idn? ( + libidn2? ( net-dns/libidn2:= ) + !libidn2? ( net-dns/libidn:= ) + ) + importd? ( + app-arch/bzip2:0= + sys-libs/zlib:0= + ) + kmod? ( >=sys-apps/kmod-15:0= ) + lz4? ( >=app-arch/lz4-0_p131:0=[${MULTILIB_USEDEP}] ) + lzma? ( >=app-arch/xz-utils-5.0.5-r1:0=[${MULTILIB_USEDEP}] ) + nat? ( net-firewall/iptables:0= ) + pam? ( virtual/pam:=[${MULTILIB_USEDEP}] ) + pcre? ( dev-libs/libpcre2 ) + qrcode? ( media-gfx/qrencode:0= ) + seccomp? ( >=sys-libs/libseccomp-2.3.3:0= ) + selinux? ( sys-libs/libselinux:0= ) + xkb? ( >=x11-libs/libxkbcommon-0.4.1:0= )" + +# baselayout-2.2 has /run +RDEPEND="${COMMON_DEPEND} + >=sys-apps/baselayout-2.2 + selinux? ( sec-policy/selinux-base-policy[systemd] ) + sysv-utils? ( !sys-apps/sysvinit ) + !sysv-utils? ( sys-apps/sysvinit ) + resolvconf? ( !net-dns/openresolv ) + !build? ( || ( + sys-apps/util-linux[kill(-)] + sys-process/procps[kill(+)] + sys-apps/coreutils[kill(-)] + ) ) + !sys-auth/nss-myhostname + ! "${locale_conf}" <<-EOF + # This file has been created by the sys-apps/systemd ebuild. + # See locale.conf(5) and localectl(1). + + # LANG=${LANG} + EOF + eend ${?} || FAIL=1 + fi + fi + + if [[ ! -L ${envd_locale} ]]; then + # now, if env.d/??locale is not a symlink (to locale.conf)... + if [[ -e ${envd_locale} ]]; then + # ...warn the user that he has duplicate locale settings + ewarn + ewarn "To ensure consistent behavior, you should replace ${envd_locale}" + ewarn "with a symlink to ${locale_conf}. Please migrate your settings" + ewarn "and create the symlink with the following command:" + ewarn "ln -s -n -f ../locale.conf ${envd_locale}" + ewarn + else + # ...or just create the symlink if there's nothing here + ebegin "Creating ${envd_locale_def} -> ../locale.conf symlink" + ln -n -s ../locale.conf "${envd_locale_def}" + eend ${?} || FAIL=1 + fi + fi +} + +pkg_postinst() { + newusergroup() { + enewgroup "$1" + enewuser "$1" -1 -1 -1 "$1" + } + + enewgroup input + enewgroup kvm 78 + enewgroup render + enewgroup systemd-journal + newusergroup systemd-bus-proxy + newusergroup systemd-coredump + newusergroup systemd-journal-gateway + newusergroup systemd-journal-remote + newusergroup systemd-journal-upload + newusergroup systemd-network + newusergroup systemd-resolve + newusergroup systemd-timesync + + systemd_update_catalog + + # Keep this here in case the database format changes so it gets updated + # when required. Despite that this file is owned by sys-apps/hwids. + if has_version "sys-apps/hwids[udev]"; then + udevadm hwdb --update --root="${EROOT}" + fi + + udev_reload || FAIL=1 + + # Bug 465468, make sure locales are respect, and ensure consistency + # between OpenRC & systemd + migrate_locale + + systemd_reenable systemd-networkd.service systemd-resolved.service + + if [[ -z ${ROOT} && -d /run/systemd/system ]]; then + ebegin "Reexecuting system manager" + systemctl daemon-reexec + eend $? + fi + + if [[ ${FAIL} ]]; then + eerror "One of the postinst commands failed. Please check the postinst output" + eerror "for errors. You may need to clean up your system and/or try installing" + eerror "systemd again." + eerror + fi +} + +pkg_prerm() { + # If removing systemd completely, remove the catalog database. + if [[ ! ${REPLACED_BY_VERSION} ]]; then + rm -f -v "${EROOT}"/var/lib/systemd/catalog/database + fi +} -- cgit v1.2.3-65-gdbad