diff options
author | P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> | 2023-07-08 01:05:27 +0300 |
---|---|---|
committer | P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> | 2023-12-31 16:58:43 +0300 |
commit | 7f53998bd3726c808abf8b0c4950e25db29d9ea2 (patch) | |
tree | 72543541bb498087ff726a8996bddebfe87229ac /meta-openbmc-mods/meta-common | |
parent | 9ad1806592d6c8e3111b9c26db1882f2af49d64c (diff) | |
download | openbmc-7f53998bd3726c808abf8b0c4950e25db29d9ea2.tar.xz |
Update to internal 1-1.11-1
Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common')
103 files changed, 8347 insertions, 768 deletions
diff --git a/meta-openbmc-mods/meta-common/classes/github-releases.bbclass b/meta-openbmc-mods/meta-common/classes/github-releases.bbclass new file mode 100644 index 000000000..ed83b8373 --- /dev/null +++ b/meta-openbmc-mods/meta-common/classes/github-releases.bbclass @@ -0,0 +1,3 @@ +GITHUB_BASE_URI ?= "https://github.com/${BPN}/${BPN}/releases/" +UPSTREAM_CHECK_URI ?= "${GITHUB_BASE_URI}" +UPSTREAM_CHECK_REGEX ?= "releases/tag/v?(?P<pver>\d+(\.\d+)+)" diff --git a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass index b0227e381..fe1e2b30d 100644 --- a/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass +++ b/meta-openbmc-mods/meta-common/classes/obmc-phosphor-image-common.bbclass @@ -76,7 +76,6 @@ IMAGE_INSTALL:append = " \ configure-usb-c \ zip \ peci-pcie \ - collectd \ " IMAGE_INSTALL:append = " ${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'pfr-manager', '', d)}" diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi/CVE-2023-1981.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi/CVE-2023-1981.patch new file mode 100644 index 000000000..d1f05b7b7 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi/CVE-2023-1981.patch @@ -0,0 +1,53 @@ +From a2696da2f2c50ac43b6c4903f72290d5c3fa9f6f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com> +Date: Thu, 17 Nov 2022 01:51:53 +0100 +Subject: [PATCH] Emit error if requested service is not found + +It currently just crashes instead of replying with error. Check return +value and emit error instead of passing NULL pointer to reply. + +Fixes #375 +--- + avahi-daemon/dbus-protocol.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/avahi-daemon/dbus-protocol.c b/avahi-daemon/dbus-protocol.c +index 70d7687bc..406d0b441 100644 +--- a/avahi-daemon/dbus-protocol.c ++++ b/avahi-daemon/dbus-protocol.c +@@ -375,10 +375,14 @@ static DBusHandlerResult dbus_get_alternative_host_name(DBusConnection *c, DBusM + } + + t = avahi_alternative_host_name(n); +- avahi_dbus_respond_string(c, m, t); +- avahi_free(t); ++ if (t) { ++ avahi_dbus_respond_string(c, m, t); ++ avahi_free(t); + +- return DBUS_HANDLER_RESULT_HANDLED; ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } else { ++ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Hostname not found"); ++ } + } + + static DBusHandlerResult dbus_get_alternative_service_name(DBusConnection *c, DBusMessage *m, DBusError *error) { +@@ -389,10 +393,14 @@ static DBusHandlerResult dbus_get_alternative_service_name(DBusConnection *c, DB + } + + t = avahi_alternative_service_name(n); +- avahi_dbus_respond_string(c, m, t); +- avahi_free(t); ++ if (t) { ++ avahi_dbus_respond_string(c, m, t); ++ avahi_free(t); + +- return DBUS_HANDLER_RESULT_HANDLED; ++ return DBUS_HANDLER_RESULT_HANDLED; ++ } else { ++ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Service not found"); ++ } + } + + static DBusHandlerResult dbus_create_new_entry_group(DBusConnection *c, DBusMessage *m, DBusError *error) { diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi_%.bbappend b/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi_%.bbappend index fa58d9726..06343a29d 100644 --- a/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-connectivity/avahi/avahi_%.bbappend @@ -1,4 +1,5 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += " \ + file://CVE-2023-1981.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0003-Add-support-for-io_pgetevents_time64-syscall.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0003-Add-support-for-io_pgetevents_time64-syscall.patch new file mode 100644 index 000000000..d62b9344c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0003-Add-support-for-io_pgetevents_time64-syscall.patch @@ -0,0 +1,62 @@ +From 5b5e2985f355c8e99c196d9ce5d02c15bebadfbc Mon Sep 17 00:00:00 2001 +From: Alistair Francis <alistair.francis@wdc.com> +Date: Thu, 29 Aug 2019 13:56:21 -0700 +Subject: [PATCH] Add support for io_pgetevents_time64 syscall + +32-bit architectures that are y2038 safe don't include syscalls that use +32-bit time_t. Instead these architectures have suffixed syscalls that +always use a 64-bit time_t. In the case of the io_getevents syscall the +syscall has been replaced with the io_pgetevents_time64 syscall instead. + +This patch changes the io_getevents() function to use the correct +syscall based on the avaliable syscalls and the time_t size. We will +only use the new 64-bit time_t syscall if the architecture is using a +64-bit time_t. This is to avoid having to deal with 32/64-bit +conversions and relying on a 64-bit timespec struct on 32-bit time_t +platforms. As of Linux 5.3 there are no 32-bit time_t architectures +without __NR_io_getevents. In the future if a 32-bit time_t architecture +wants to use the 64-bit syscalls we can handle the conversion. + +This fixes build failures on 32-bit RISC-V. + +Signed-off-by: Alistair Francis <alistair.francis@wdc.com> + +Reviewed-by: Richard Levitte <levitte@openssl.org> +Reviewed-by: Paul Dale <paul.dale@oracle.com> +(Merged from https://github.com/openssl/openssl/pull/9819) +Upstream-Status: Accepted +--- + engines/e_afalg.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/engines/e_afalg.c b/engines/e_afalg.c +index dacbe358cb..99516cb1bb 100644 +--- a/engines/e_afalg.c ++++ b/engines/e_afalg.c +@@ -125,7 +125,23 @@ static ossl_inline int io_getevents(aio_context_t ctx, long min, long max, + struct io_event *events, + struct timespec *timeout) + { ++#if defined(__NR_io_getevents) + return syscall(__NR_io_getevents, ctx, min, max, events, timeout); ++#elif defined(__NR_io_pgetevents_time64) ++ /* Let's only support the 64 suffix syscalls for 64-bit time_t. ++ * This simplifies the code for us as we don't need to use a 64-bit ++ * version of timespec with a 32-bit time_t and handle converting ++ * between 64-bit and 32-bit times and check for overflows. ++ */ ++ if (sizeof(timeout->tv_sec) == 8) ++ return syscall(__NR_io_pgetevents_time64, ctx, min, max, events, timeout, NULL); ++ else { ++ errno = ENOSYS; ++ return -1; ++ } ++#else ++# error "We require either the io_getevents syscall or __NR_io_pgetevents_time64." ++#endif + } + + static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, +-- +2.30.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0004-Fixup-support-for-io_pgetevents_time64-syscall.patch b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0004-Fixup-support-for-io_pgetevents_time64-syscall.patch new file mode 100644 index 000000000..c8bc6f5c6 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl/0004-Fixup-support-for-io_pgetevents_time64-syscall.patch @@ -0,0 +1,99 @@ +From e5499a3cac1e823c3e0697e8667e952317b70cc8 Mon Sep 17 00:00:00 2001 +From: Alistair Francis <alistair.francis@wdc.com> +Date: Thu, 4 Mar 2021 12:10:11 -0500 +Subject: [PATCH] Fixup support for io_pgetevents_time64 syscall + +This is a fixup for the original commit 5b5e2985f355c8e99c196d9ce5d02c15bebadfbc +"Add support for io_pgetevents_time64 syscall" that didn't correctly +work for 32-bit architecutres with a 64-bit time_t that aren't RISC-V. + +For a full discussion of the issue see: +https://github.com/openssl/openssl/commit/5b5e2985f355c8e99c196d9ce5d02c15bebadfbc + +Signed-off-by: Alistair Francis <alistair.francis@wdc.com> + +Reviewed-by: Tomas Mraz <tomas@openssl.org> +Reviewed-by: Paul Dale <pauli@openssl.org> +(Merged from https://github.com/openssl/openssl/pull/14432) +Upstream-Status: Accepted +--- + engines/e_afalg.c | 55 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 42 insertions(+), 13 deletions(-) + +diff --git a/engines/e_afalg.c b/engines/e_afalg.c +index 9480d7c24b..4e9d67db2d 100644 +--- a/engines/e_afalg.c ++++ b/engines/e_afalg.c +@@ -124,27 +124,56 @@ static ossl_inline int io_read(aio_context_t ctx, long n, struct iocb **iocb) + return syscall(__NR_io_submit, ctx, n, iocb); + } + ++/* A version of 'struct timespec' with 32-bit time_t and nanoseconds. */ ++struct __timespec32 ++{ ++ __kernel_long_t tv_sec; ++ __kernel_long_t tv_nsec; ++}; ++ + static ossl_inline int io_getevents(aio_context_t ctx, long min, long max, + struct io_event *events, + struct timespec *timeout) + { ++#if defined(__NR_io_pgetevents_time64) ++ /* Check if we are a 32-bit architecture with a 64-bit time_t */ ++ if (sizeof(*timeout) != sizeof(struct __timespec32)) { ++ int ret = syscall(__NR_io_pgetevents_time64, ctx, min, max, events, ++ timeout, NULL); ++ if (ret == 0 || errno != ENOSYS) ++ return ret; ++ } ++#endif ++ + #if defined(__NR_io_getevents) +- return syscall(__NR_io_getevents, ctx, min, max, events, timeout); +-#elif defined(__NR_io_pgetevents_time64) +- /* Let's only support the 64 suffix syscalls for 64-bit time_t. +- * This simplifies the code for us as we don't need to use a 64-bit +- * version of timespec with a 32-bit time_t and handle converting +- * between 64-bit and 32-bit times and check for overflows. +- */ +- if (sizeof(timeout->tv_sec) == 8) +- return syscall(__NR_io_pgetevents_time64, ctx, min, max, events, timeout, NULL); ++ if (sizeof(*timeout) == sizeof(struct __timespec32)) ++ /* ++ * time_t matches our architecture length, we can just use ++ * __NR_io_getevents ++ */ ++ return syscall(__NR_io_getevents, ctx, min, max, events, timeout); + else { +- errno = ENOSYS; +- return -1; ++ /* ++ * We don't have __NR_io_pgetevents_time64, but we are using a ++ * 64-bit time_t on a 32-bit architecture. If we can fit the ++ * timeout value in a 32-bit time_t, then let's do that ++ * and then use the __NR_io_getevents syscall. ++ */ ++ if (timeout && timeout->tv_sec == (long)timeout->tv_sec) { ++ struct __timespec32 ts32; ++ ++ ts32.tv_sec = (__kernel_long_t) timeout->tv_sec; ++ ts32.tv_nsec = (__kernel_long_t) timeout->tv_nsec; ++ ++ return syscall(__NR_io_getevents, ctx, min, max, events, ts32); ++ } else { ++ return syscall(__NR_io_getevents, ctx, min, max, events, NULL); ++ } + } +-#else +-# error "We require either the io_getevents syscall or __NR_io_pgetevents_time64." + #endif ++ ++ errno = ENOSYS; ++ return -1; + } + + static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, +-- +2.30.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1l.bb b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1u.bb index dc2a8ccff..6e0ad9ac4 100644 --- a/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1l.bb +++ b/meta-openbmc-mods/meta-common/recipes-connectivity/openssl/openssl_1.1.1u.bb @@ -11,23 +11,28 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=d343e62fc9c833710bbbed25f27364c8" DEPENDS = "hostperl-runtime-native" -SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz \ +PV = "1.0+git${SRCPV}" + +S = "${WORKDIR}/git" + +SRCREV = "3f499b24f3bcd66db022074f7e8b4f6ee266a3ae" + +SRC_URI = "git://github.com/openssl/openssl.git;branch=OpenSSL_1_1_1-stable;protocol=https \ file://run-ptest \ file://0001-skip-test_symbol_presence.patch \ file://0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch \ file://afalg.patch \ file://reproducible.patch \ - file://CVE-2022-0778.patch \ - file://CVE-2022-1292-Fix-openssl-c_rehash.patch \ - file://CVE-2022-2068-Fix-file-operations-in-c_rehash.patch \ - file://CVE-2022-2097-openssl-Fix-AES-OCB-encryptdecrypt-for-x86-AES-NI.patch \ " SRC_URI:append:class-nativesdk = " \ file://environment.d-openssl.sh \ " -SRC_URI[sha256sum] = "0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1" +SRC_URI:append:riscv32 = " \ + file://0003-Add-support-for-io_pgetevents_time64-syscall.patch \ + file://0004-Fixup-support-for-io_pgetevents_time64-syscall.patch \ + " inherit lib_package multilib_header multilib_script ptest MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash" @@ -37,6 +42,8 @@ PACKAGECONFIG:class-native = "" PACKAGECONFIG:class-nativesdk = "" PACKAGECONFIG[cryptodev-linux] = "enable-devcryptoeng,disable-devcryptoeng,cryptodev-linux,,cryptodev-module" +PACKAGECONFIG[no-tls1] = "no-tls1" +PACKAGECONFIG[no-tls1_1] = "no-tls1_1" B = "${WORKDIR}/build" do_configure[cleandirs] = "${B}" @@ -56,6 +63,20 @@ EXTRA_OECONF:class-nativesdk = "--with-rand-seed=os,devrandom" CFLAGS:append:class-native = " -DOPENSSLDIR=/not/builtin -DENGINESDIR=/not/builtin" CFLAGS:append:class-nativesdk = " -DOPENSSLDIR=/not/builtin -DENGINESDIR=/not/builtin" +# Disable deprecated crypto algorithms +# Retained for compatibilty +# des (curl) +# dh (python-ssl) +# dsa (rpm) +# md4 (cyrus-sasl freeradius hostapd) +# bf (wvstreams postgresql x11vnc crda znc cfengine) +# rc4 (freerdp librtorrent ettercap xrdp transmission pam-ssh-agent-auth php) +# rc2 (mailx) +# psk (qt5) +# srp (libest) +# whirlpool (qca) +DEPRECATED_CRYPTO_FLAGS = "no-ssl no-idea no-rc5 no-md2 no-camellia no-mdc2 no-scrypt no-seed no-siphash no-sm2 no-sm3 no-sm4" + do_configure () { os=${HOST_OS} case $os in @@ -117,6 +138,9 @@ do_configure () { linux-sparc | linux-supersparc) target=linux-sparcv9 ;; + mingw32-x86_64) + target=mingw64 + ;; esac useprefix=${prefix} @@ -126,7 +150,7 @@ do_configure () { # WARNING: do not set compiler/linker flags (-I/-D etc.) in EXTRA_OECONF, as they will fully replace the # environment variables set by bitbake. Adjust the environment variables instead. HASHBANGPERL="/usr/bin/env perl" PERL=perl PERL5LIB="${S}/external/perl/Text-Template-1.46/lib/" \ - perl ${S}/Configure ${EXTRA_OECONF} ${PACKAGECONFIG_CONFARGS} --prefix=$useprefix --openssldir=${libdir}/ssl-1.1 --libdir=${libdir} $target + perl ${S}/Configure ${EXTRA_OECONF} ${PACKAGECONFIG_CONFARGS} ${DEPRECATED_CRYPTO_FLAGS} --prefix=$useprefix --openssldir=${libdir}/ssl-1.1 --libdir=${libdir} $target perl ${B}/configdata.pm --dump } @@ -184,6 +208,10 @@ do_install_ptest () { install -d ${D}${PTEST_PATH}/engines install -m755 ${B}/engines/ossltest.so ${D}${PTEST_PATH}/engines + + # seems to be needed with perl 5.32.1 + install -d ${D}${PTEST_PATH}/util/perl/recipes + cp ${D}${PTEST_PATH}/test/recipes/tconversion.pl ${D}${PTEST_PATH}/util/perl/recipes/ } # Add the openssl.cnf file to the openssl-conf package. Make the libcrypto @@ -195,21 +223,30 @@ PACKAGES =+ "libcrypto libssl openssl-conf ${PN}-engines ${PN}-misc" FILES:libcrypto = "${libdir}/libcrypto${SOLIBS}" FILES:libssl = "${libdir}/libssl${SOLIBS}" -FILES:openssl-conf = "${sysconfdir}/ssl/openssl.cnf" +FILES:openssl-conf = "${sysconfdir}/ssl/openssl.cnf \ + ${libdir}/ssl-1.1/openssl.cnf* \ + " FILES:${PN}-engines = "${libdir}/engines-1.1" -FILES:${PN}-misc = "${libdir}/ssl-1.1/misc" +# ${prefix} comes from what we pass into --prefix at configure time (which is used for INSTALLTOP) +FILES:${PN}-engines:append:mingw32:class-nativesdk = " ${prefix}${libdir}/engines-1_1" +FILES:${PN}-misc = "${libdir}/ssl-1.1/misc ${bindir}/c_rehash" FILES:${PN} =+ "${libdir}/ssl-1.1/*" FILES:${PN}:append:class-nativesdk = " ${SDKPATHNATIVE}/environment-setup.d/openssl.sh" CONFFILES:openssl-conf = "${sysconfdir}/ssl/openssl.cnf" RRECOMMENDS:libcrypto += "openssl-conf" +RDEPENDS:${PN}-misc = "perl" RDEPENDS:${PN}-ptest += "openssl-bin perl perl-modules bash" +RDEPENDS:${PN}-bin += "openssl-conf" + BBCLASSEXTEND = "native nativesdk" CVE_PRODUCT = "openssl:openssl" +CVE_VERSION_SUFFIX = "alphabetical" + # Only affects OpenSSL >= 1.1.1 in combination with Apache < 2.4.37 # Apache in meta-webserver is already recent enough CVE_CHECK_WHITELIST += "CVE-2019-0190" diff --git a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/CVE-2022-30065.patch b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/CVE-2022-30065.patch new file mode 100644 index 000000000..2f23931be --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox/CVE-2022-30065.patch @@ -0,0 +1,48 @@ +From 4bae4300986d0ed3d43f92600bd291ae3d302a99 Mon Sep 17 00:00:00 2001 +From: Yaswanth Reddy M <yaswanthx.reddy.munukuru@intel.com> +Date: Fri, 5 May 2023 08:55:31 +0000 +Subject: [PATCH] Subject: awk: fix use after free (CVE-2022-30065) + +fixes https://bugs.busybox.net/show_bug.cgi?id=14781 + +function old new delta +evaluate 3343 3357 +14 + +Signed-off-by: Yaswanth Reddy M <yaswanthx.reddy.munukuru@intel.com> +--- + editors/awk.c | 3 +++ + testsuite/awk.tests | 5 +++++ + 2 files changed, 8 insertions(+) + +diff --git a/editors/awk.c b/editors/awk.c +index 3adbca7..43a17c0 100644 +--- a/editors/awk.c ++++ b/editors/awk.c +@@ -3094,6 +3094,9 @@ static var *evaluate(node *op, var *res) + + case XC( OC_MOVE ): + debug_printf_eval("MOVE\n"); ++ /* make sure that we never return a temp var */ ++ if (L.v == TMPVAR0) ++ L.v = res; + /* if source is a temporary string, jusk relink it to dest */ + if (R.v == TMPVAR1 + && !(R.v->type & VF_NUMBER) +diff --git a/testsuite/awk.tests b/testsuite/awk.tests +index dc2ae2e..072c8fc 100755 +--- a/testsuite/awk.tests ++++ b/testsuite/awk.tests +@@ -462,5 +462,10 @@ testing "awk \"cmd\" | getline" \ + "awk 'BEGIN { \"echo HELLO\" | getline; print }'" \ + "HELLO\n" \ + '' '' ++testing 'awk assign while test' \ ++ "awk '\$1==\$1=\"foo\" {print \$1}'" \ ++ "foo\n" \ ++ "" \ ++ "foo" + + exit $FAILCOUNT +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend index 42a52e0d7..b9c654068 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/busybox/busybox_%.bbappend @@ -4,6 +4,7 @@ SRC_URI += " \ file://enable.cfg \ file://CVE-2022-28391_1.patch \ file://CVE-2022-28391_2.patch \ + file://CVE-2022-30065.patch \ " SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks','file://dev-only.cfg','',d)}" diff --git a/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42010.patch b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42010.patch new file mode 100644 index 000000000..d2693ed69 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42010.patch @@ -0,0 +1,114 @@ +From 9d07424e9011e3bbe535e83043d335f3093d2916 Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Tue, 13 Sep 2022 15:10:22 +0100 +Subject: [PATCH] dbus-marshal-validate: Check brackets in signature nest +correctly + +In debug builds with assertions enabled, a signature with incorrectly +nested `()` and `{}`, for example `a{i(u}` or `(a{ii)}`, could result +in an assertion failure. + +In production builds without assertions enabled, a signature with +incorrectly nested `()` and `{}` could potentially result in a crash +or incorrect message parsing, although we do not have a concrete example +of either of these failure modes. + +Thanks: Evgeny Vereshchagin +Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/418 +Resolves: CVE-2022-42010 +Signed-off-by: Simon McVittie <smcv@collabora.com> +--- + dbus/dbus-marshal-validate.c | 38 +++++++++++++++++++++++++++++++++++- + 1 file changed, 37 insertions(+), 1 deletion(-) + +diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c +index 4d492f3f3..ae68414dd 100644 +--- a/dbus/dbus-marshal-validate.c ++++ b/dbus/dbus-marshal-validate.c +@@ -62,6 +62,8 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + + int element_count; + DBusList *element_count_stack; ++ char opened_brackets[DBUS_MAXIMUM_TYPE_RECURSION_DEPTH * 2 + 1] = { '\0' }; ++ char last_bracket; + + result = DBUS_VALID; + element_count_stack = NULL; +@@ -93,6 +95,10 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + + while (p != end) + { ++ _dbus_assert (struct_depth + dict_entry_depth >= 0); ++ _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets)); ++ _dbus_assert (opened_brackets[struct_depth + dict_entry_depth] == '\0'); ++ + switch (*p) + { + case DBUS_TYPE_BYTE: +@@ -136,6 +142,10 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + goto out; + } + ++ _dbus_assert (struct_depth + dict_entry_depth >= 1); ++ _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets)); ++ _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0'); ++ opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_STRUCT_BEGIN_CHAR; + break; + + case DBUS_STRUCT_END_CHAR: +@@ -151,9 +161,20 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + goto out; + } + ++ _dbus_assert (struct_depth + dict_entry_depth >= 1); ++ _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets)); ++ last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1]; ++ ++ if (last_bracket != DBUS_STRUCT_BEGIN_CHAR) ++ { ++ result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED; ++ goto out; ++ } ++ + _dbus_list_pop_last (&element_count_stack); + + struct_depth -= 1; ++ opened_brackets[struct_depth + dict_entry_depth] = '\0'; + break; + + case DBUS_DICT_ENTRY_BEGIN_CHAR: +@@ -178,6 +199,10 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + goto out; + } + ++ _dbus_assert (struct_depth + dict_entry_depth >= 1); ++ _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets)); ++ _dbus_assert (opened_brackets[struct_depth + dict_entry_depth - 1] == '\0'); ++ opened_brackets[struct_depth + dict_entry_depth - 1] = DBUS_DICT_ENTRY_BEGIN_CHAR; + break; + + case DBUS_DICT_ENTRY_END_CHAR: +@@ -186,8 +211,19 @@ _dbus_validate_signature_with_reason (const DBusString *type_str, + result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; + goto out; + } +- ++ ++ _dbus_assert (struct_depth + dict_entry_depth >= 1); ++ _dbus_assert (struct_depth + dict_entry_depth < _DBUS_N_ELEMENTS (opened_brackets)); ++ last_bracket = opened_brackets[struct_depth + dict_entry_depth - 1]; ++ ++ if (last_bracket != DBUS_DICT_ENTRY_BEGIN_CHAR) ++ { ++ result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED; ++ goto out; ++ } ++ + dict_entry_depth -= 1; ++ opened_brackets[struct_depth + dict_entry_depth] = '\0'; + + element_count = + _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack)); +-- +GitLab + diff --git a/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42011.patch b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42011.patch new file mode 100644 index 000000000..9284dd666 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42011.patch @@ -0,0 +1,55 @@ +From 079bbf16186e87fb0157adf8951f19864bc2ed69 Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Mon, 12 Sep 2022 13:14:18 +0100 +Subject: [PATCH] dbus-marshal-validate: Validate length of arrays of + fixed-length items + +This fast-path previously did not check that the array was made up +of an integer number of items. This could lead to assertion failures +and out-of-bounds accesses during subsequent message processing (which +assumes that the message has already been validated), particularly after +the addition of _dbus_header_remove_unknown_fields(), which makes it +more likely that dbus-daemon will apply non-trivial edits to messages. + +Thanks: Evgeny Vereshchagin +Fixes: e61f13cf "Bug 18064 - more efficient validation for fixed-size type arrays" +Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/413 +Resolves: CVE-2022-42011 +Signed-off-by: Simon McVittie <smcv@collabora.com> +--- + dbus/dbus-marshal-validate.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c +index ae68414dd..7d0d6cf72 100644 +--- a/dbus/dbus-marshal-validate.c ++++ b/dbus/dbus-marshal-validate.c +@@ -503,13 +503,24 @@ validate_body_helper (DBusTypeReader *reader, + */ + if (dbus_type_is_fixed (array_elem_type)) + { ++ /* Note that fixed-size types all have sizes equal to ++ * their alignments, so this is really the item size. */ ++ alignment = _dbus_type_get_alignment (array_elem_type); ++ _dbus_assert (alignment == 1 || alignment == 2 || ++ alignment == 4 || alignment == 8); ++ ++ /* Because the alignment is a power of 2, this is ++ * equivalent to: (claimed_len % alignment) != 0, ++ * but avoids slower integer division */ ++ if ((claimed_len & (alignment - 1)) != 0) ++ return DBUS_INVALID_ARRAY_LENGTH_INCORRECT; ++ + /* bools need to be handled differently, because they can + * have an invalid value + */ + if (array_elem_type == DBUS_TYPE_BOOLEAN) + { + dbus_uint32_t v; +- alignment = _dbus_type_get_alignment (array_elem_type); + + while (p < array_end) + { +-- +GitLab + diff --git a/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42012.patch b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42012.patch new file mode 100644 index 000000000..53b0e92ff --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus/CVE-2022-42012.patch @@ -0,0 +1,71 @@ +From 236f16e444e88a984cf12b09225e0f8efa6c5b44 Mon Sep 17 00:00:00 2001 +From: Simon McVittie <smcv@collabora.com> +Date: Fri, 30 Sep 2022 13:46:31 +0100 +Subject: [PATCH] dbus-marshal-byteswap: Byte-swap Unix fd indexes if needed + +When a D-Bus message includes attached file descriptors, the body of the +message contains unsigned 32-bit indexes pointing into an out-of-band +array of file descriptors. Some D-Bus APIs like GLib's GDBus refer to +these indexes as "handles" for the associated fds (not to be confused +with a Windows HANDLE, which is a kernel object). + +The assertion message removed by this commit is arguably correct up to +a point: fd-passing is only reasonable on a local machine, and no known +operating system allows processes of differing endianness even on a +multi-endian ARM or PowerPC CPU, so it makes little sense for the sender +to specify a byte-order that differs from the byte-order of the recipient. + +However, this doesn't account for the fact that a malicious sender +doesn't have to restrict itself to only doing things that make sense. +On a system with untrusted local users, a message sender could crash +the system dbus-daemon (a denial of service) by sending a message in +the opposite endianness that contains handles to file descriptors. + +Before this commit, if assertions are enabled, attempting to byteswap +a fd index would cleanly crash the message recipient with an assertion +failure. If assertions are disabled, attempting to byteswap a fd index +would silently do nothing without advancing the pointer p, causing the +message's type and the pointer into its contents to go out of sync, which +can result in a subsequent crash (the crash demonstrated by fuzzing was +a use-after-free, but other failure modes might be possible). + +In principle we could resolve this by rejecting wrong-endianness messages +from a local sender, but it's actually simpler and less code to treat +wrong-endianness messages as valid and byteswap them. + +Thanks: Evgeny Vereshchagin +Fixes: ba7daa60 "unix-fd: add basic marshalling code for unix fds" +Resolves: https://gitlab.freedesktop.org/dbus/dbus/-/issues/417 +Resolves: CVE-2022-42012 +Signed-off-by: Simon McVittie <smcv@collabora.com> +--- + dbus/dbus-marshal-byteswap.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/dbus/dbus-marshal-byteswap.c b/dbus/dbus-marshal-byteswap.c +index e9de6f02a..9dd1246f9 100644 +--- a/dbus/dbus-marshal-byteswap.c ++++ b/dbus/dbus-marshal-byteswap.c +@@ -62,6 +62,7 @@ byteswap_body_helper (DBusTypeReader *reader, + case DBUS_TYPE_BOOLEAN: + case DBUS_TYPE_INT32: + case DBUS_TYPE_UINT32: ++ case DBUS_TYPE_UNIX_FD: + { + p = _DBUS_ALIGN_ADDRESS (p, 4); + *((dbus_uint32_t*)p) = DBUS_UINT32_SWAP_LE_BE (*((dbus_uint32_t*)p)); +@@ -192,11 +193,6 @@ byteswap_body_helper (DBusTypeReader *reader, + } + break; + +- case DBUS_TYPE_UNIX_FD: +- /* fds can only be passed on a local machine, so byte order must always match */ +- _dbus_assert_not_reached("attempted to byteswap unix fds which makes no sense"); +- break; +- + default: + _dbus_assert_not_reached ("invalid typecode in supposedly-validated signature"); + break; +-- +GitLab + diff --git a/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus_%.bbappend new file mode 100644 index 000000000..af073e92a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/dbus/dbus_%.bbappend @@ -0,0 +1,6 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += " \ + file://CVE-2022-42010.patch \ + file://CVE-2022-42011.patch \ + file://CVE-2022-42012.patch \ + " diff --git a/meta-openbmc-mods/meta-common/recipes-core/expat/expat/CVE-2022-43680.patch b/meta-openbmc-mods/meta-common/recipes-core/expat/expat/CVE-2022-43680.patch new file mode 100644 index 000000000..b19647736 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/expat/expat/CVE-2022-43680.patch @@ -0,0 +1,109 @@ +From 5290462a7ea1278a8d5c0d5b2860d4e244f997e4 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Tue, 20 Sep 2022 02:44:34 +0200 +Subject: [PATCH 1/3] lib: Fix overeager DTD destruction in + XML_ExternalEntityParserCreate + +--- + lib/xmlparse.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/lib/xmlparse.c b/lib/xmlparse.c +index aacd6e7fc..57bf103cc 100644 +--- a/lib/xmlparse.c ++++ b/lib/xmlparse.c +@@ -1068,6 +1068,14 @@ parserCreate(const XML_Char *encodingName, + parserInit(parser, encodingName); + + if (encodingName && ! parser->m_protocolEncodingName) { ++ if (dtd) { ++ // We need to stop the upcoming call to XML_ParserFree from happily ++ // destroying parser->m_dtd because the DTD is shared with the parent ++ // parser and the only guard that keeps XML_ParserFree from destroying ++ // parser->m_dtd is parser->m_isParamEntity but it will be set to ++ // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all). ++ parser->m_dtd = NULL; ++ } + XML_ParserFree(parser); + return NULL; + } + +From 43992e4ae25fc3dc0eec0cd3a29313555d56aee2 Mon Sep 17 00:00:00 2001 +From: Sebastian Pipping <sebastian@pipping.org> +Date: Mon, 19 Sep 2022 18:16:15 +0200 +Subject: [PATCH 2/3] tests: Cover overeager DTD destruction in + XML_ExternalEntityParserCreate + +--- + tests/runtests.c | 49 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/tests/runtests.c b/tests/runtests.c +index 245fe9bda..acb744dd4 100644 +--- a/tests/runtests.c ++++ b/tests/runtests.c +@@ -10208,6 +10208,53 @@ START_TEST(test_alloc_long_notation) { + } + END_TEST + ++static int XMLCALL ++external_entity_parser_create_alloc_fail_handler(XML_Parser parser, ++ const XML_Char *context, ++ const XML_Char *base, ++ const XML_Char *systemId, ++ const XML_Char *publicId) { ++ UNUSED_P(base); ++ UNUSED_P(systemId); ++ UNUSED_P(publicId); ++ ++ if (context != NULL) ++ fail("Unexpected non-NULL context"); ++ ++ // The following number intends to fail the upcoming allocation in line ++ // "parser->m_protocolEncodingName = copyString(encodingName, ++ // &(parser->m_mem));" in function parserInit. ++ allocation_count = 3; ++ ++ const XML_Char *const encodingName = XCS("UTF-8"); // needs something non-NULL ++ const XML_Parser ext_parser ++ = XML_ExternalEntityParserCreate(parser, context, encodingName); ++ if (ext_parser != NULL) ++ fail( ++ "Call to XML_ExternalEntityParserCreate was expected to fail out-of-memory"); ++ ++ allocation_count = ALLOC_ALWAYS_SUCCEED; ++ return XML_STATUS_ERROR; ++} ++ ++START_TEST(test_alloc_reset_after_external_entity_parser_create_fail) { ++ const char *const text = "<!DOCTYPE doc SYSTEM 'foo'><doc/>"; ++ ++ XML_SetExternalEntityRefHandler( ++ g_parser, external_entity_parser_create_alloc_fail_handler); ++ XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS); ++ ++ if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE) ++ != XML_STATUS_ERROR) ++ fail("Call to parse was expected to fail"); ++ ++ if (XML_GetErrorCode(g_parser) != XML_ERROR_EXTERNAL_ENTITY_HANDLING) ++ fail("Call to parse was expected to fail from the external entity handler"); ++ ++ XML_ParserReset(g_parser, NULL); ++} ++END_TEST ++ + static void + nsalloc_setup(void) { + XML_Memory_Handling_Suite memsuite = {duff_allocator, duff_reallocator, free}; +@@ -12401,6 +12448,8 @@ make_suite(void) { + tcase_add_test(tc_alloc, test_alloc_long_public_id); + tcase_add_test(tc_alloc, test_alloc_long_entity_value); + tcase_add_test(tc_alloc, test_alloc_long_notation); ++ tcase_add_test__ifdef_xml_dtd( ++ tc_alloc, test_alloc_reset_after_external_entity_parser_create_fail); + + suite_add_tcase(s, tc_nsalloc); + tcase_add_checked_fixture(tc_nsalloc, nsalloc_setup, nsalloc_teardown); + + diff --git a/meta-openbmc-mods/meta-common/recipes-core/expat/expat_2.4.5.bb b/meta-openbmc-mods/meta-common/recipes-core/expat/expat_2.4.5.bb index 852ba0baf..616838aa3 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/expat/expat_2.4.5.bb +++ b/meta-openbmc-mods/meta-common/recipes-core/expat/expat_2.4.5.bb @@ -12,6 +12,7 @@ SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TA file://run-ptest \ file://CVE-2022-40674_1.patch \ file://CVE-2022-40674_2.patch \ + file://CVE-2022-43680.patch \ " UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/" diff --git a/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2021-3998.patch b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2021-3998.patch new file mode 100644 index 000000000..8a6533070 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2021-3998.patch @@ -0,0 +1,173 @@ +From a48cfb100aa47d349cd1b80d0efcca3231b6bfcd Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@sourceware.org> +Date: Thu, 13 Jan 2022 11:28:36 +0530 +Subject: [PATCH 1/2] realpath: Set errno to ENAMETOOLONG for result larger + than PATH_MAX [BZ #28770] + +realpath returns an allocated string when the result exceeds PATH_MAX, +which is unexpected when its second argument is not NULL. This results +in the second argument (resolved) being uninitialized and also results +in a memory leak since the caller expects resolved to be the same as the +returned value. + +Return NULL and set errno to ENAMETOOLONG if the result exceeds +PATH_MAX. This fixes [BZ #28770], which is CVE-2021-3998. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +(cherry picked from commit ee8d5e33adb284601c00c94687bc907e10aec9bb) +(cherry picked from commit f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5 + with conflict resoluation in stdlib/Makefile and NEWS) +--- + NEWS | 4 +++ + stdlib/Makefile | 2 +- + stdlib/canonicalize.c | 12 +++++++-- + stdlib/tst-realpath-toolong.c | 49 +++++++++++++++++++++++++++++++++++ + 4 files changed, 64 insertions(+), 3 deletions(-) + create mode 100644 stdlib/tst-realpath-toolong.c + +diff --git a/NEWS b/NEWS +index 028ed04ca2..0c3b1c2556 100644 +--- a/NEWS ++++ b/NEWS +@@ -210,6 +210,10 @@ Security related changes: + legacy function could result in a stack-based buffer overflow when + using the "unix" protocol. Reported by Martin Sebor. + ++ CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath ++ function could result in a memory leak and potential access of ++ uninitialized memory. Reported by Qualys. ++ + The following bugs are resolved with this release: + + [4737] libc: fork is not async-signal-safe +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 7c15549caf..22de3867be 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -88,7 +88,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + tst-swapcontext1 tst-setcontext4 tst-setcontext5 \ + tst-setcontext6 tst-setcontext7 tst-setcontext8 \ + tst-setcontext9 tst-bz20544 tst-canon-bz26341 \ +- tst-realpath ++ tst-realpath tst-realpath-toolong + + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete +diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c +index cac1f73d74..20033b4885 100644 +--- a/stdlib/canonicalize.c ++++ b/stdlib/canonicalize.c +@@ -400,8 +400,16 @@ realpath_stk (const char *name, char *resolved, + + error: + *dest++ = '\0'; +- if (resolved != NULL && dest - rname <= get_path_max ()) +- rname = strcpy (resolved, rname); ++ if (resolved != NULL) ++ { ++ if (dest - rname <= get_path_max ()) ++ rname = strcpy (resolved, rname); ++ else ++ { ++ failed = true; ++ __set_errno (ENAMETOOLONG); ++ } ++ } + + error_nomem: + scratch_buffer_free (&extra_buffer); +diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c +new file mode 100644 +index 0000000000..8bed772460 +--- /dev/null ++++ b/stdlib/tst-realpath-toolong.c +@@ -0,0 +1,49 @@ ++/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds ++ NAME_MAX. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <limits.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <support/check.h> ++#include <support/temp_file.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++ ++#define BASENAME "tst-realpath-toolong." ++ ++int ++do_test (void) ++{ ++ char *base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ char buf[PATH_MAX + 1]; ++ const char *res = realpath (".", buf); ++ ++ /* canonicalize.c states that if the real path is >= PATH_MAX, then ++ realpath returns NULL and sets ENAMETOOLONG. */ ++ TEST_VERIFY (res == NULL); ++ TEST_VERIFY (errno == ENAMETOOLONG); ++ ++ free (base); ++ return 0; ++} ++ ++#include <support/test-driver.c> +-- +2.25.1 + + +From a4bc5841640e57f8d216e818b07cdd4c74f62815 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@sourceware.org> +Date: Mon, 24 Jan 2022 21:36:41 +0530 +Subject: [PATCH 2/2] realpath: Avoid overwriting preexisting error + (CVE-2021-3998) + +Set errno and failure for paths that are too long only if no other error +occurred earlier. + +Related: BZ #28770 + +Reviewed-by: Andreas Schwab <schwab@linux-m68k.org> +Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +(cherry picked from commit 84d2d0fe20bdf94feed82b21b4d7d136db471f03) +(cherry picked from commit d084965adc7baa8ea804427cccf973cea556d697) +--- + stdlib/canonicalize.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c +index 20033b4885..fdeca42b83 100644 +--- a/stdlib/canonicalize.c ++++ b/stdlib/canonicalize.c +@@ -404,7 +404,7 @@ error: + { + if (dest - rname <= get_path_max ()) + rname = strcpy (resolved, rname); +- else ++ else if (!failed) + { + failed = true; + __set_errno (ENAMETOOLONG); +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2023-0687.patch b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2023-0687.patch new file mode 100644 index 000000000..da0e43686 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc/CVE-2023-0687.patch @@ -0,0 +1,77 @@ +From 801af9fafd4689337ebf27260aa115335a0cb2bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= + =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru> +Date: Sat, 4 Feb 2023 14:41:38 +0300 +Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The `__monstartup()` allocates a buffer used to store all the data +accumulated by the monitor. + +The size of this buffer depends on the size of the internal structures +used and the address range for which the monitor is activated, as well +as on the maximum density of call instructions and/or callable functions +that could be potentially on a segment of executable code. + +In particular a hash table of arcs is placed at the end of this buffer. +The size of this hash table is calculated in bytes as + p->fromssize = p->textsize / HASHFRACTION; + +but actually should be + p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + +This results in writing beyond the end of the allocated buffer when an +added arc corresponds to a call near from the end of the monitored +address range, since `_mcount()` check the incoming caller address for +monitored range but not the intermediate result hash-like index that +uses to write into the table. + +It should be noted that when the results are output to `gmon.out`, the +table is read to the last element calculated from the allocated size in +bytes, so the arcs stored outside the buffer boundary did not fall into +`gprof` for analysis. Thus this "feature" help me to found this bug +during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438 + +Just in case, I will explicitly note that the problem breaks the +`make test t=gmon/tst-gmon-dso` added for Bug 29438. +There, the arc of the `f3()` call disappears from the output, since in +the DSO case, the call to `f3` is located close to the end of the +monitored range. + +Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru> + +Another minor error seems a related typo in the calculation of +`kcountsize`, but since kcounts are smaller than froms, this is +actually to align the p->froms data. + +Co-authored-by: DJ Delorie <dj@redhat.com> +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +--- + gmon/gmon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gmon/gmon.c b/gmon/gmon.c +index dee64803ada..bf76358d5b1 100644 +--- a/gmon/gmon.c ++++ b/gmon/gmon.c +@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc) + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; ++ /* This looks like a typo, but it's here to align the p->froms ++ section. */ + p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; +@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc) + instead of integer division. Precompute shift amount. */ + p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; + } +- p->fromssize = p->textsize / HASHFRACTION; ++ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; + diff --git a/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc_%.bbappend index be793e5e8..96c4947ad 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/glibc/glibc_%.bbappend @@ -8,4 +8,6 @@ SRC_URI += " \ file://0001-CVE-2022-23219.patch \ file://0002-CVE-2022-23219.patch \ file://CVE-2021-43396.patch \ + file://CVE-2021-3998.patch \ + file://CVE-2023-0687.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40303.patch b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40303.patch new file mode 100644 index 000000000..ecb134edf --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40303.patch @@ -0,0 +1,618 @@ +From c846986356fc149915a74972bf198abc266bc2c0 Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Thu, 25 Aug 2022 17:43:08 +0200 +Subject: [PATCH] [CVE-2022-40303] Fix integer overflows with XML_PARSE_HUGE + +Also impose size limits when XML_PARSE_HUGE is set. Limit size of names +to XML_MAX_TEXT_LENGTH (10 million bytes) and other content to +XML_MAX_HUGE_LENGTH (1 billion bytes). + +Move some the length checks to the end of the respective loop to make +them strict. + +xmlParseEntityValue didn't have a length limitation at all. But without +XML_PARSE_HUGE, this should eventually trigger an error in xmlGROW. + +Thanks to Maddie Stone working with Google Project Zero for the report! +--- + parser.c | 233 +++++++++++++++++++++++++++++-------------------------- + 1 file changed, 121 insertions(+), 112 deletions(-) + +diff --git a/parser.c b/parser.c +index 93f031be..79479979 100644 +--- a/parser.c ++++ b/parser.c +@@ -102,6 +102,8 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt); + * * + ************************************************************************/ + ++#define XML_MAX_HUGE_LENGTH 1000000000 ++ + #define XML_PARSER_BIG_ENTITY 1000 + #define XML_PARSER_LOT_ENTITY 5000 + +@@ -552,7 +554,7 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info) + errmsg = "Malformed declaration expecting version"; + break; + case XML_ERR_NAME_TOO_LONG: +- errmsg = "Name too long use XML_PARSE_HUGE option"; ++ errmsg = "Name too long"; + break; + #if 0 + case: +@@ -3202,6 +3204,9 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNameComplex++; +@@ -3267,7 +3272,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + } +@@ -3293,13 +3299,13 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) { + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); + return(NULL); + } +@@ -3338,7 +3344,10 @@ const xmlChar * + xmlParseName(xmlParserCtxtPtr ctxt) { + const xmlChar *in; + const xmlChar *ret; +- int count = 0; ++ size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + GROW; + +@@ -3362,8 +3371,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) { + in++; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; +- if ((count > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (count > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name"); + return(NULL); + } +@@ -3384,6 +3392,9 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + size_t startPosition = 0; + + #ifdef DEBUG +@@ -3404,17 +3415,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */ + (xmlIsNameChar(ctxt, c) && (c != ':'))) { + if (count++ > XML_PARSER_CHUNK_SIZE) { +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); +- return(NULL); +- } + count = 0; + GROW; + if (ctxt->instate == XML_PARSER_EOF) + return(NULL); + } +- len += l; ++ if (len <= INT_MAX - l) ++ len += l; + NEXTL(l); + c = CUR_CHAR(l); + if (c == 0) { +@@ -3432,8 +3439,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + c = CUR_CHAR(l); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3459,7 +3465,10 @@ static const xmlChar * + xmlParseNCName(xmlParserCtxtPtr ctxt) { + const xmlChar *in, *e; + const xmlChar *ret; +- int count = 0; ++ size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNCName++; +@@ -3484,8 +3493,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) { + goto complex; + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; +- if ((count > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (count > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3567,6 +3575,9 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + const xmlChar *cur = *str; + int len = 0, l; + int c; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseStringName++; +@@ -3602,12 +3613,6 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + if (len + 10 > max) { + xmlChar *tmp; + +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); +- xmlFree(buffer); +- return(NULL); +- } + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); +@@ -3621,14 +3626,18 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) { + COPY_BUF(l,buffer,len,c); + cur += l; + c = CUR_SCHAR(cur, l); ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); ++ xmlFree(buffer); ++ return(NULL); ++ } + } + buffer[len] = 0; + *str = cur; + return(buffer); + } + } +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(NULL); + } +@@ -3655,6 +3664,9 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + int len = 0, l; + int c; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + + #ifdef DEBUG + nbParseNmToken++; +@@ -3706,12 +3718,6 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + if (len + 10 > max) { + xmlChar *tmp; + +- if ((max > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); +- xmlFree(buffer); +- return(NULL); +- } + max *= 2; + tmp = (xmlChar *) xmlRealloc(buffer, + max * sizeof(xmlChar)); +@@ -3725,6 +3731,11 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + COPY_BUF(l,buffer,len,c); + NEXTL(l); + c = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); ++ xmlFree(buffer); ++ return(NULL); ++ } + } + buffer[len] = 0; + return(buffer); +@@ -3732,8 +3743,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) { + } + if (len == 0) + return(NULL); +- if ((len > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken"); + return(NULL); + } +@@ -3759,6 +3769,9 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int c, l; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + xmlChar stop; + xmlChar *ret = NULL; + const xmlChar *cur = NULL; +@@ -3818,6 +3831,12 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) { + GROW; + c = CUR_CHAR(l); + } ++ ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED, ++ "entity value too long\n"); ++ goto error; ++ } + } + buf[len] = 0; + if (ctxt->instate == XML_PARSER_EOF) +@@ -3905,6 +3924,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + xmlChar *rep = NULL; + size_t len = 0; + size_t buf_size = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int c, l, in_space = 0; + xmlChar *current = NULL; + xmlEntityPtr ent; +@@ -3936,16 +3958,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + while (((NXT(0) != limit) && /* checked */ + (IS_CHAR(c)) && (c != '<')) && + (ctxt->instate != XML_PARSER_EOF)) { +- /* +- * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE +- * special option is given +- */ +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, +- "AttValue length too long\n"); +- goto mem_error; +- } + if (c == '&') { + in_space = 0; + if (NXT(1) == '#') { +@@ -4093,6 +4105,11 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + } + GROW; + c = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, ++ "AttValue length too long\n"); ++ goto mem_error; ++ } + } + if (ctxt->instate == XML_PARSER_EOF) + goto error; +@@ -4114,16 +4131,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) { + } else + NEXT; + +- /* +- * There we potentially risk an overflow, don't allow attribute value of +- * length more than INT_MAX it is a very reasonable assumption ! +- */ +- if (len >= INT_MAX) { +- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, +- "AttValue length too long\n"); +- goto mem_error; +- } +- + if (attlen != NULL) *attlen = (int) len; + return(buf); + +@@ -4194,6 +4201,9 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; + int cur, l; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + xmlChar stop; + int state = ctxt->instate; + int count = 0; +@@ -4221,13 +4231,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + if (len + 5 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); +- xmlFree(buf); +- ctxt->instate = (xmlParserInputState) state; +- return(NULL); +- } + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { +@@ -4256,6 +4259,12 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) { + SHRINK; + cur = CUR_CHAR(l); + } ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral"); ++ xmlFree(buf); ++ ctxt->instate = (xmlParserInputState) state; ++ return(NULL); ++ } + } + buf[len] = 0; + ctxt->instate = (xmlParserInputState) state; +@@ -4283,6 +4292,9 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + int len = 0; + int size = XML_PARSER_BUFFER_SIZE; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_TEXT_LENGTH : ++ XML_MAX_NAME_LENGTH; + xmlChar cur; + xmlChar stop; + int count = 0; +@@ -4310,12 +4322,6 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + if (len + 1 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_NAME_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID"); +- xmlFree(buf); +- return(NULL); +- } + size *= 2; + tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar)); + if (tmp == NULL) { +@@ -4343,6 +4349,11 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) { + SHRINK; + cur = CUR; + } ++ if (len > maxLength) { ++ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID"); ++ xmlFree(buf); ++ return(NULL); ++ } + } + buf[len] = 0; + if (cur != stop) { +@@ -4742,6 +4753,9 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + int r, rl; + int cur, l; + size_t count = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int inputid; + + inputid = ctxt->input->id; +@@ -4787,13 +4801,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + if ((r == '-') && (q == '-')) { + xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL); + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, +- "Comment too big found", NULL); +- xmlFree (buf); +- return; +- } + if (len + 5 >= size) { + xmlChar *new_buf; + size_t new_size; +@@ -4831,6 +4838,13 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, + GROW; + cur = CUR_CHAR(l); + } ++ ++ if (len > maxLength) { ++ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, ++ "Comment too big found", NULL); ++ xmlFree (buf); ++ return; ++ } + } + buf[len] = 0; + if (cur == 0) { +@@ -4875,6 +4889,9 @@ xmlParseComment(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + size_t size = XML_PARSER_BUFFER_SIZE; + size_t len = 0; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + xmlParserInputState state; + const xmlChar *in; + size_t nbchar = 0; +@@ -4958,8 +4975,7 @@ get_more: + buf[len] = 0; + } + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if (len > maxLength) { + xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED, + "Comment too big found", NULL); + xmlFree (buf); +@@ -5159,6 +5175,9 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + xmlChar *buf = NULL; + size_t len = 0; + size_t size = XML_PARSER_BUFFER_SIZE; ++ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + int cur, l; + const xmlChar *target; + xmlParserInputState state; +@@ -5234,14 +5253,6 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + return; + } + count = 0; +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +- "PI %s too big found", target); +- xmlFree(buf); +- ctxt->instate = state; +- return; +- } + } + COPY_BUF(l,buf,len,cur); + NEXTL(l); +@@ -5251,15 +5262,14 @@ xmlParsePI(xmlParserCtxtPtr ctxt) { + GROW; + cur = CUR_CHAR(l); + } ++ if (len > maxLength) { ++ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, ++ "PI %s too big found", target); ++ xmlFree(buf); ++ ctxt->instate = state; ++ return; ++ } + } +- if ((len > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +- "PI %s too big found", target); +- xmlFree(buf); +- ctxt->instate = state; +- return; +- } + buf[len] = 0; + if (cur != '?') { + xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED, +@@ -8954,6 +8964,9 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + const xmlChar *in = NULL, *start, *end, *last; + xmlChar *ret = NULL; + int line, col; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + + GROW; + in = (xmlChar *) CUR_PTR; +@@ -8993,8 +9006,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + start = in; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9007,8 +9019,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + if ((*in++ == 0x20) && (*in == 0x20)) break; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9041,16 +9052,14 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + last = last + delta; + } + end = ctxt->input->end; +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); + } + } + } +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9063,8 +9072,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + col++; + if (in >= end) { + GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end) +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9072,8 +9080,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc, + } + } + last = in; +- if (((in - start) > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { ++ if ((in - start) > maxLength) { + xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED, + "AttValue length too long\n"); + return(NULL); +@@ -9763,6 +9770,9 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + int s, sl; + int cur, l; + int count = 0; ++ int maxLength = (ctxt->options & XML_PARSE_HUGE) ? ++ XML_MAX_HUGE_LENGTH : ++ XML_MAX_TEXT_LENGTH; + + /* Check 2.6.0 was NXT(0) not RAW */ + if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) { +@@ -9796,13 +9806,6 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + if (len + 5 >= size) { + xmlChar *tmp; + +- if ((size > XML_MAX_TEXT_LENGTH) && +- ((ctxt->options & XML_PARSE_HUGE) == 0)) { +- xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED, +- "CData section too big found", NULL); +- xmlFree (buf); +- return; +- } + tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar)); + if (tmp == NULL) { + xmlFree(buf); +@@ -9829,6 +9832,12 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) { + } + NEXTL(l); + cur = CUR_CHAR(l); ++ if (len > maxLength) { ++ xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED, ++ "CData section too big found\n"); ++ xmlFree(buf); ++ return; ++ } + } + buf[len] = 0; + ctxt->instate = XML_PARSER_CONTENT; +-- +GitLab + diff --git a/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40304.patch b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40304.patch new file mode 100644 index 000000000..b6a48587d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2/CVE-2022-40304.patch @@ -0,0 +1,101 @@ +From 1b41ec4e9433b05bb0376be4725804c54ef1d80b Mon Sep 17 00:00:00 2001 +From: Nick Wellnhofer <wellnhofer@aevum.de> +Date: Wed, 31 Aug 2022 22:11:25 +0200 +Subject: [PATCH] [CVE-2022-40304] Fix dict corruption caused by entity + reference cycles + +When an entity reference cycle is detected, the entity content is +cleared by setting its first byte to zero. But the entity content might +be allocated from a dict. In this case, the dict entry becomes corrupted +leading to all kinds of logic errors, including memory errors like +double-frees. + +Stop storing entity content, orig, ExternalID and SystemID in a dict. +These values are unlikely to occur multiple times in a document, so they +shouldn't have been stored in a dict in the first place. + +Thanks to Ned Williamson and Nathan Wachholz working with Google Project +Zero for the report! +--- + entities.c | 55 ++++++++++++++++-------------------------------------- + 1 file changed, 16 insertions(+), 39 deletions(-) + +diff --git a/entities.c b/entities.c +index 84435515..d4e5412e 100644 +--- a/entities.c ++++ b/entities.c +@@ -128,36 +128,19 @@ xmlFreeEntity(xmlEntityPtr entity) + if ((entity->children) && (entity->owner == 1) && + (entity == (xmlEntityPtr) entity->children->parent)) + xmlFreeNodeList(entity->children); +- if (dict != NULL) { +- if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name))) +- xmlFree((char *) entity->name); +- if ((entity->ExternalID != NULL) && +- (!xmlDictOwns(dict, entity->ExternalID))) +- xmlFree((char *) entity->ExternalID); +- if ((entity->SystemID != NULL) && +- (!xmlDictOwns(dict, entity->SystemID))) +- xmlFree((char *) entity->SystemID); +- if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI))) +- xmlFree((char *) entity->URI); +- if ((entity->content != NULL) +- && (!xmlDictOwns(dict, entity->content))) +- xmlFree((char *) entity->content); +- if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig))) +- xmlFree((char *) entity->orig); +- } else { +- if (entity->name != NULL) +- xmlFree((char *) entity->name); +- if (entity->ExternalID != NULL) +- xmlFree((char *) entity->ExternalID); +- if (entity->SystemID != NULL) +- xmlFree((char *) entity->SystemID); +- if (entity->URI != NULL) +- xmlFree((char *) entity->URI); +- if (entity->content != NULL) +- xmlFree((char *) entity->content); +- if (entity->orig != NULL) +- xmlFree((char *) entity->orig); +- } ++ if ((entity->name != NULL) && ++ ((dict == NULL) || (!xmlDictOwns(dict, entity->name)))) ++ xmlFree((char *) entity->name); ++ if (entity->ExternalID != NULL) ++ xmlFree((char *) entity->ExternalID); ++ if (entity->SystemID != NULL) ++ xmlFree((char *) entity->SystemID); ++ if (entity->URI != NULL) ++ xmlFree((char *) entity->URI); ++ if (entity->content != NULL) ++ xmlFree((char *) entity->content); ++ if (entity->orig != NULL) ++ xmlFree((char *) entity->orig); + xmlFree(entity); + } + +@@ -193,18 +176,12 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type, + ret->SystemID = xmlStrdup(SystemID); + } else { + ret->name = xmlDictLookup(dict, name, -1); +- if (ExternalID != NULL) +- ret->ExternalID = xmlDictLookup(dict, ExternalID, -1); +- if (SystemID != NULL) +- ret->SystemID = xmlDictLookup(dict, SystemID, -1); ++ ret->ExternalID = xmlStrdup(ExternalID); ++ ret->SystemID = xmlStrdup(SystemID); + } + if (content != NULL) { + ret->length = xmlStrlen(content); +- if ((dict != NULL) && (ret->length < 5)) +- ret->content = (xmlChar *) +- xmlDictLookup(dict, content, ret->length); +- else +- ret->content = xmlStrndup(content, ret->length); ++ ret->content = xmlStrndup(content, ret->length); + } else { + ret->length = 0; + ret->content = NULL; +-- +GitLab + diff --git a/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2_%.bbappend index 4011c8759..1d2993a8d 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/libxml/libxml2_%.bbappend @@ -2,4 +2,6 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += "file://CVE-2022-23308-Use-after-free-of-ID-and-IDREF.patch \ file://CVE-2022-29824-Fix-integer-overflows-in-xmlBuf-and-xmlBuffer.patch \ + file://CVE-2022-40303.patch \ + file://CVE-2022-40304.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses.inc b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses.inc new file mode 100644 index 000000000..367f3b19f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses.inc @@ -0,0 +1,327 @@ +SUMMARY = "The New Curses library" +DESCRIPTION = "SVr4 and XSI-Curses compatible curses library and terminfo tools including tic, infocmp, captoinfo. Supports color, multiple highlights, forms-drawing characters, and automatic recognition of keypad and function-key sequences. Extensions include resizable windows and mouse support on both xterm and Linux console using the gpm library." +HOMEPAGE = "http://www.gnu.org/software/ncurses/ncurses.html" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://COPYING;md5=c5a4600fdef86384c41ca33ecc70a4b8;endline=27" +SECTION = "libs" +DEPENDS = "ncurses-native" +DEPENDS:class-native = "" + +BINCONFIG = "${bindir}/ncurses5-config ${bindir}/ncursesw5-config \ + ${bindir}/ncurses6-config ${bindir}/ncursesw6-config" + +inherit autotools binconfig-disabled multilib_header pkgconfig + +# Upstream has useful patches at times at ftp://invisible-island.net/ncurses/ +SRC_URI = "git://github.com/mirror/ncurses.git;protocol=https;branch=master" + +EXTRA_AUTORECONF = "-I m4" + +CACHED_CONFIGUREVARS = "cf_cv_func_nanosleep=yes" +CACHED_CONFIGUREVARS:append:linux = " cf_cv_working_poll=yes" + +EXTRASITECONFIG = "CFLAGS='${CFLAGS} -I${SYSROOT_DESTDIR}${includedir}'" + +# Whether to enable separate widec libraries; must be 'true' or 'false' +# +# TODO: remove this variable when widec is supported in every setup? +ENABLE_WIDEC ?= "true" + +# _GNU_SOURCE is required for widec stuff and is detected automatically +# for target objects. But it must be set manually for native and sdk +# builds. +BUILD_CPPFLAGS += "-D_GNU_SOURCE" + +# natives don't generally look in base_libdir +base_libdir:class-native = "${libdir}" + +# Display corruption occurs on 64 bit hosts without these settings +# This was derrived from the upstream debian ncurses which uses +# these settings for 32 and 64 bit hosts. +EXCONFIG_ARGS = "" +EXCONFIG_ARGS:class-native = " \ + --disable-lp64 \ + --with-chtype='long' \ + --with-mmask-t='long'" +EXCONFIG_ARGS:class-nativesdk = " \ + --disable-lp64 \ + --with-chtype='long' \ + --with-mmask-t='long'" + +PACKAGES_DYNAMIC = "^${PN}-lib.*" + +# Fall back to the host termcap / terminfo for -nativesdk and -native +# The reality is a work around for strange problems with things like +# "bitbake -c menuconfig busybox" where it cannot find the terminfo +# because the sstate had a hard coded search path. Until this is fixed +# another way this is deemed good enough. +EX_TERMCAP = "" +EX_TERMCAP:class-native = ":/etc/termcap:/usr/share/misc/termcap" +EX_TERMCAP:class-nativesdk = ":/etc/termcap:/usr/share/misc/termcap" +EX_TERMINFO = "" +EX_TERMINFO:class-native = ":/etc/terminfo:/usr/share/terminfo:/usr/share/misc/terminfo:/lib/terminfo" +EX_TERMINFO:class-nativesdk = ":/etc/terminfo:/usr/share/terminfo:/usr/share/misc/terminfo:/lib/terminfo" +EX_TERMLIB ?= "tinfo" + +# Helper function for do_configure to allow multiple configurations +# $1 the directory to run configure in +# $@ the arguments to pass to configure +ncurses_configure() { + mkdir -p $1 + cd $1 + shift + oe_runconf \ + --without-debug \ + --without-ada \ + --without-gpm \ + --enable-hard-tabs \ + --enable-xmc-glitch \ + --enable-colorfgbg \ + --with-termpath='${sysconfdir}/termcap:${datadir}/misc/termcap${EX_TERMCAP}' \ + --with-terminfo-dirs='${sysconfdir}/terminfo:${datadir}/terminfo${EX_TERMINFO}' \ + --with-shared \ + --disable-big-core \ + --program-prefix= \ + --with-ticlib \ + --with-termlib=${EX_TERMLIB} \ + --enable-sigwinch \ + --enable-pc-files \ + --disable-rpath-hack \ + ${EXCONFIG_ARGS} \ + --with-manpage-format=normal \ + --without-manpage-renames \ + --disable-stripping \ + "$@" || return 1 + cd .. +} + +# Override the function from the autotools class; ncurses requires a +# patched autoconf213 to generate the configure script. This autoconf +# is not available so that the shipped script will be used. +do_configure() { + #Remove ${includedir} from CPPFLAGS, need for cross compile + sed -i 's#-I${cf_includedir}##g' ${S}/configure || die "sed CPPFLAGS" + + # The --enable-pc-files requires PKG_CONFIG_LIBDIR existed + mkdir -p ${PKG_CONFIG_LIBDIR} + ( cd ${S}; gnu-configize --force ) + ncurses_configure "narrowc" || \ + return 1 + ! ${ENABLE_WIDEC} || \ + ncurses_configure "widec" "--enable-widec" "--without-progs" + +} + +do_compile() { + oe_runmake -C narrowc libs + oe_runmake -C narrowc/progs + + ! ${ENABLE_WIDEC} || \ + oe_runmake -C widec libs +} + +# set of expected differences between narrowc and widec header +# +# TODO: the NCURSES_CH_T difference can cause real problems :( +_unifdef_cleanup = " \ + -e '\!/\* \$Id: curses.wide,v!,\!/\* \$Id: curses.tail,v!d' \ + -e '/^#define NCURSES_CH_T /d' \ + -e '/^#include <wchar.h>/d' \ + -e '\!^/\* .* \*/!d' \ +" + +do_test[depends] = "unifdef-native:do_populate_sysroot" +do_test[dirs] = "${S}" +do_test() { + ${ENABLE_WIDEC} || return 0 + + # make sure that the narrow and widec header are compatible + # and differ only in minor details. + unifdef -k narrowc/include/curses.h | \ + sed ${_unifdef_cleanup} > curses-narrowc.h + unifdef -k widec/include/curses.h | \ + sed ${_unifdef_cleanup} > curses-widec.h + + diff curses-narrowc.h curses-widec.h +} + +# Split original _install_opts to two parts. +# One is the options to install contents, the other is the parameters \ +# when running command "make install" +# Note that install.libs will also implicitly install header files, +# so we do not need to explicitly specify install.includes. +# Doing so could in fact result in a race condition, as both targets +# (install.libs and install.includes) would install the same headers +# at the same time + +_install_opts = " install.libs install.man " + +_install_cfgs = "\ + DESTDIR='${D}' \ + PKG_CONFIG_LIBDIR='${libdir}/pkgconfig' \ +" + +do_install() { + # Order of installation is important; widec installs a 'curses.h' + # header with more definitions and must be installed last hence. + # Compatibility of these headers will be checked in 'do_test()'. + oe_runmake -C narrowc ${_install_cfgs} ${_install_opts} \ + install.progs + + # The install.data should run after install.libs, otherwise + # there would be a race issue in a very critical conditon, since + # tic will be run by install.data, and tic needs libtinfo.so + # which would be regenerated by install.libs. + oe_runmake -C narrowc ${_install_cfgs} \ + install.data + + + ! ${ENABLE_WIDEC} || \ + oe_runmake -C widec ${_install_cfgs} ${_install_opts} + + cd narrowc + + # include some basic terminfo files + # stolen ;) from gentoo and modified a bit + for x in ansi console dumb linux rxvt screen screen-256color sun vt52 vt100 vt102 vt200 vt220 xterm-color xterm-xfree86 xterm-256color + do + local termfile="$(find "${D}${datadir}/terminfo/" -name "${x}" 2>/dev/null)" + local basedir="$(basename $(dirname "${termfile}"))" + + if [ -n "${termfile}" ] + then + install -d ${D}${sysconfdir}/terminfo/${basedir} + mv ${termfile} ${D}${sysconfdir}/terminfo/${basedir}/ + ln -s /etc/terminfo/${basedir}/${x} \ + ${D}${datadir}/terminfo/${basedir}/${x} + fi + done + # i think we can use xterm-color as default xterm + if [ -e ${D}${sysconfdir}/terminfo/x/xterm-color ] + then + ln -sf xterm-color ${D}${sysconfdir}/terminfo/x/xterm + fi + + # When changing ${libdir} to e.g. /usr/lib/myawesomelib/ ncurses + # still installs '/usr/lib/terminfo', so try to rm both + # the proper path and a slightly hardcoded one + rm -f ${D}${libdir}/terminfo ${D}${prefix}/lib/terminfo + + # create linker scripts for libcurses.so and libncurses to + # link against -ltinfo when needed. Some builds might break + # else when '-Wl,--no-copy-dt-needed-entries' has been set in + # linker flags. + for i in libncurses libncursesw; do + f=${D}${libdir}/$i.so + test -h $f || continue + rm -f $f + echo '/* GNU ld script */' >$f + echo "INPUT($i.so.5 AS_NEEDED(-ltinfo))" >>$f + done + + # Make sure that libcurses is linked so that it gets -ltinfo + # also, this should be addressed upstream really. + ln -sf libncurses.so ${D}${libdir}/libcurses.so + + # create libtermcap.so linker script for backward compatibility + f=${D}${libdir}/libtermcap.so + echo '/* GNU ld script */' >$f + echo 'INPUT(AS_NEEDED(-ltinfo))' >>$f + + if [ ! -d "${D}${base_libdir}" ]; then + # Setting base_libdir to libdir as is done in the -native + # case will skip this code + mkdir -p ${D}${base_libdir} + mv ${D}${libdir}/libncurses.so.* ${D}${base_libdir} + ! ${ENABLE_WIDEC} || \ + mv ${D}${libdir}/libncursesw.so.* ${D}${base_libdir} + + mv ${D}${libdir}/libtinfo.so.* ${D}${base_libdir} + rm ${D}${libdir}/libtinfo.so + + # Use ln -rs to ensure this is a relative link despite absolute paths + # (as we can't know the relationship between base_libdir and libdir). + ln -rs ${D}${base_libdir}/libtinfo.so.5 ${D}${libdir}/libtinfo.so + fi + if [ -d "${D}${includedir}/ncurses" ]; then + for f in `find ${D}${includedir}/ncurses -name "*.h"` + do + f=`basename $f` + test -e ${D}${includedir}/$f && continue + ln -sf ncurses/$f ${D}${includedir}/$f + done + fi + oe_multilib_header curses.h +} + +python populate_packages:prepend () { + libdir = d.expand("${libdir}") + base_libdir = d.expand("${base_libdir}") + pnbase = d.expand("${PN}-lib%s") + do_split_packages(d, libdir, r'^lib(.*)\.so\..*', pnbase, 'ncurses %s library', prepend=True, extra_depends = '', allow_links=True) + if libdir is not base_libdir: + do_split_packages(d, base_libdir, r'^lib(.*)\.so\..*', pnbase, 'ncurses %s library', prepend=True, extra_depends = '', allow_links=True) +} + + +inherit update-alternatives + +ALTERNATIVE_PRIORITY = "100" + +ALTERNATIVE:ncurses-tools:class-target = "clear reset" +ALTERNATIVE:ncurses-terminfo:class-target = "st st-256color" + +ALTERNATIVE_LINK_NAME[st] = "${datadir}/terminfo/s/st" + +ALTERNATIVE_LINK_NAME[st-256color] = "${datadir}/terminfo/s/st-256color" + +BBCLASSEXTEND = "native nativesdk" + +PACKAGES += " \ + ${PN}-tools \ + ${PN}-terminfo-base \ + ${PN}-terminfo \ +" + +FILES:${PN} = "\ + ${bindir}/tput \ + ${bindir}/tset \ + ${bindir}/ncurses5-config \ + ${bindir}/ncursesw5-config \ + ${bindir}/ncurses6-config \ + ${bindir}/ncursesw6-config \ + ${datadir}/tabset \ +" + +# This keeps only tput/tset in ncurses +# clear/reset are in already busybox +FILES:${PN}-tools = "\ + ${bindir}/tic \ + ${bindir}/toe \ + ${bindir}/infotocap \ + ${bindir}/captoinfo \ + ${bindir}/infocmp \ + ${bindir}/clear${@['', '.${BPN}']['${CLASSOVERRIDE}' == 'class-target']} \ + ${bindir}/reset${@['', '.${BPN}']['${CLASSOVERRIDE}' == 'class-target']} \ + ${bindir}/tack \ + ${bindir}/tabs \ +" + +# 'reset' is a symlink to 'tset' which is in the 'ncurses' package +RDEPENDS:${PN}-tools = "${PN} ${PN}-terminfo-base" + +FILES:${PN}-terminfo = "\ + ${datadir}/terminfo \ +" + +FILES:${PN}-terminfo-base = "\ + ${sysconfdir}/terminfo \ +" + +RSUGGESTS:${PN}-libtinfo = "${PN}-terminfo" +RRECOMMENDS:${PN}-libtinfo = "${PN}-terminfo-base" + +# Putting terminfo into the sysroot adds around 2800 files to +# each recipe specific sysroot. We can live without this, particularly +# as many recipes may have native and target copies. +SYSROOT_DIRS:remove = "${datadir}" diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-Fix-heap-buffer-overflow-in-captoinfo.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-Fix-heap-buffer-overflow-in-captoinfo.patch deleted file mode 100644 index 420a19b41..000000000 --- a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-Fix-heap-buffer-overflow-in-captoinfo.patch +++ /dev/null @@ -1,47 +0,0 @@ -From ad135388ac66b7c8276b0899d9b43433e2faffa6 Mon Sep 17 00:00:00 2001 -From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> -Date: Tue, 7 Dec 2021 23:58:53 +0000 -Subject: [PATCH] Fix heap-buffer-overflow in captoinfo - -This has been picked up from http://cvsweb.netbsd.org/ -bsdweb.cgi/pkgsrc/devel/ncurses/patches/Attic/ -patch-ncurses_tinfo_captoinfo.c -?rev=1.1&content-type=text/x-cvsweb-markup - -Thomas Dickey is the owner of this patch. -This fix is a part of -https://github.com/ThomasDickey/ncurses-snapshots/ -commit/63ca9e061f4644795d6f3f559557f3e1ed8c738b#diff- -7e95c7bc5f213e9be438e69a9d5d0f261a14952bcbd692f7b9014217b8047340 - -Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> ---- - ncurses/tinfo/captoinfo.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/ncurses/tinfo/captoinfo.c b/ncurses/tinfo/captoinfo.c -index 8b3b83d1..c9741405 100644 ---- a/ncurses/tinfo/captoinfo.c -+++ b/ncurses/tinfo/captoinfo.c -@@ -216,12 +216,15 @@ cvtchar(register const char *sp) - } - break; - case '^': -+ len = 2; - c = UChar(*++sp); -- if (c == '?') -+ if (c == '?') { - c = 127; -- else -+ } else if (c == '\0') { -+ len = 1; -+ } else { - c &= 0x1f; -- len = 2; -+ } - break; - default: - c = UChar(*sp); --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-patch-20230408-CVE-2023-29491.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-patch-20230408-CVE-2023-29491.patch new file mode 100644 index 000000000..6e4301e35 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-patch-20230408-CVE-2023-29491.patch @@ -0,0 +1,1432 @@ +From 50dd6dac94847a1aec06deb324eedef627f1829c Mon Sep 17 00:00:00 2001 +From: Saravanan Palanisamy <saravanan.palanisamy@intel.com> +Date: Wed, 24 May 2023 12:45:20 +0000 +Subject: [PATCH] ncurses 6.4 - patch 20230408 (for CVE-2023-29491) + +From eb51b1ea1f75a0ec17c9c5937cb28df1e8eeec56 Mon Sep 17 00:00:00 2001 +From: "Thomas E. Dickey" <dickey@invisible-island.net> +Date: Sun, 9 Apr 2023 00:08:25 +0000 +Subject: [PATCH 1/1] ncurses 6.4 - patch 20230408 + ++ document limitations of tparm, and error-returns in curs_terminfo.3x ++ document limitations of tgoto, and error-returns in curs_termcap.3x ++ add xterm+focus to alacritty+common (patch by Christian Duerr). ++ add "-v" option to tput, to show warnings. +> improve checks for malformed terminfo data (report/analysis by + Jonathan Bar Or, Michael Pearse, Emanuele Cozzi). + + make the parameter type/count checks in _nc_tiparm() more stringent + + update tgoto() to account for _nc_tiparm() changes + + add checks in tparm() and tiparm() for misuse of string parameters + + add special cases in tput to handle extensions Cs/Ms parameters + + ignore compiled-terminfo where the array sizes exceed the standard + +Note: +Did not cherrypick below changes from original patch as it is not applicable +Intel OpenBMC: + package/debian-mingw/changelog + package/debian-mingw64/changelog + package/debian/changelog + package/mingw-ncurses.nsi + package/mingw-ncurses.spec +--- + NEWS | 15 ++- + VERSION | 2 +- + dist.mk | 4 +- + doc/html/man/adacurses6-config.1.html | 2 +- + doc/html/man/captoinfo.1m.html | 2 +- + doc/html/man/clear.1.html | 2 +- + doc/html/man/curs_termcap.3x.html | 141 +++++++++++++++----------- + doc/html/man/curs_terminfo.3x.html | 41 +++++++- + doc/html/man/form.3x.html | 2 +- + doc/html/man/infocmp.1m.html | 2 +- + doc/html/man/infotocap.1m.html | 2 +- + doc/html/man/menu.3x.html | 2 +- + doc/html/man/ncurses.3x.html | 2 +- + doc/html/man/ncurses6-config.1.html | 2 +- + doc/html/man/panel.3x.html | 2 +- + doc/html/man/tabs.1.html | 2 +- + doc/html/man/terminfo.5.html | 2 +- + doc/html/man/tic.1m.html | 2 +- + doc/html/man/toe.1m.html | 2 +- + doc/html/man/tput.1.html | 2 +- + doc/html/man/tset.1.html | 2 +- + man/curs_termcap.3x | 26 ++++- + man/curs_terminfo.3x | 41 +++++++- + misc/terminfo.src | 9 +- + ncurses/tinfo/lib_tgoto.c | 14 ++- + ncurses/tinfo/lib_tparm.c | 120 +++++++++++++++++++--- + ncurses/tinfo/read_entry.c | 7 +- + package/ncurses.spec | 2 +- + package/ncursest.spec | 2 +- + progs/tic.c | 10 +- + progs/tparm_type.c | 13 ++- + progs/tparm_type.h | 6 +- + progs/tput.c | 61 +++++++++-- + 33 files changed, 418 insertions(+), 128 deletions(-) + +diff --git a/NEWS b/NEWS +index 66e63a39..ab0c10a2 100644 +--- a/NEWS ++++ b/NEWS +@@ -26,7 +26,7 @@ + -- sale, use or other dealings in this Software without prior written -- + -- authorization. -- + ------------------------------------------------------------------------------- +--- $Id: NEWS,v 1.3895 2022/12/31 20:43:21 tom Exp $ ++-- $Id: NEWS,v 1.3929 2023/04/08 22:24:09 tom Exp $ + ------------------------------------------------------------------------------- + + This is a log of changes that ncurses has gone through since Zeyd started +@@ -46,6 +46,19 @@ See the AUTHORS file for the corresponding full names. + Changes through 1.9.9e did not credit all contributions; + it is not possible to add this information. + ++20230408 ++ + document limitations of tparm, and error-returns in curs_terminfo.3x ++ + document limitations of tgoto, and error-returns in curs_termcap.3x ++ + add xterm+focus to alacritty+common (patch by Christian Duerr). ++ + add "-v" option to tput, to show warnings. ++ > improve checks for malformed terminfo data (report/analysis by ++ Jonathan Bar Or, Michael Pearse, Emanuele Cozzi). ++ + make the parameter type/count checks in _nc_tiparm() more stringent ++ + update tgoto() to account for _nc_tiparm() changes ++ + add checks in tparm() and tiparm() for misuse of string parameters ++ + add special cases in tput to handle extensions Cs/Ms parameters ++ + ignore compiled-terminfo where the array sizes exceed the standard ++ + 20221231 6.4 release for upload to ftp.gnu.org + + update release notes + + regenerate llib-* files. +diff --git a/VERSION b/VERSION +index e2dff67c..78269eab 100644 +--- a/VERSION ++++ b/VERSION +@@ -1 +1 @@ +-5:0:10 6.4 20221231 ++5:0:10 6.4 20230408 +diff --git a/dist.mk b/dist.mk +index ee07796b..a2986a57 100644 +--- a/dist.mk ++++ b/dist.mk +@@ -26,7 +26,7 @@ + # use or other dealings in this Software without prior written # + # authorization. # + ############################################################################## +-# $Id: dist.mk,v 1.1519 2022/12/31 20:43:21 tom Exp $ ++# $Id: dist.mk,v 1.1534 2023/04/08 13:33:20 tom Exp $ + # Makefile for creating ncurses distributions. + # + # This only needs to be used directly as a makefile by developers, but +@@ -38,7 +38,7 @@ SHELL = /bin/sh + # These define the major/minor/patch versions of ncurses. + NCURSES_MAJOR = 6 + NCURSES_MINOR = 4 +-NCURSES_PATCH = 20221231 ++NCURSES_PATCH = 20230408 + + # We don't append the patch to the version, since this only applies to releases + VERSION = $(NCURSES_MAJOR).$(NCURSES_MINOR) +diff --git a/doc/html/man/adacurses6-config.1.html b/doc/html/man/adacurses6-config.1.html +index 90587e45..fe563fe2 100644 +--- a/doc/html/man/adacurses6-config.1.html ++++ b/doc/html/man/adacurses6-config.1.html +@@ -126,7 +126,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG> + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/captoinfo.1m.html b/doc/html/man/captoinfo.1m.html +index ab99a7cf..2c914951 100644 +--- a/doc/html/man/captoinfo.1m.html ++++ b/doc/html/man/captoinfo.1m.html +@@ -199,7 +199,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="infocmp.1m.html">infocmp(1m)</A></STRONG>, <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG> + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H2><a name="h2-AUTHOR">AUTHOR</a></H2><PRE> +diff --git a/doc/html/man/clear.1.html b/doc/html/man/clear.1.html +index 74f5198b..243d57ed 100644 +--- a/doc/html/man/clear.1.html ++++ b/doc/html/man/clear.1.html +@@ -150,7 +150,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="tput.1.html">tput(1)</A></STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>, <STRONG>xterm(1)</STRONG>. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/curs_termcap.3x.html b/doc/html/man/curs_termcap.3x.html +index 9cd555ec..32699b3c 100644 +--- a/doc/html/man/curs_termcap.3x.html ++++ b/doc/html/man/curs_termcap.3x.html +@@ -1,6 +1,6 @@ + <!-- + **************************************************************************** +- * Copyright 2018-2022,2022 Thomas E. Dickey * ++ * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2017,2018 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -27,7 +27,7 @@ + * sale, use or other dealings in this Software without prior written * + * authorization. * + **************************************************************************** +- * @Id: curs_termcap.3x,v 1.56 2022/02/12 20:05:11 tom Exp @ ++ * @Id: curs_termcap.3x,v 1.57 2023/04/08 21:43:01 tom Exp @ + --> + <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"> + <HTML> +@@ -148,27 +148,32 @@ + first parameter is merely a placeholder. + + <STRONG>o</STRONG> Normally the ncurses library is compiled with terminfo support. In +- that case, <STRONG>tgoto</STRONG> uses <STRONG><A HREF="curs_terminfo.3x.html">tparm(3x)</A></STRONG> (a more capable formatter). ++ that case, <STRONG>tgoto</STRONG> uses an internal version of <STRONG><A HREF="curs_terminfo.3x.html">tparm(3x)</A></STRONG> (a more ca- ++ pable formatter). + +- However, <STRONG>tparm</STRONG> is not a <EM>termcap</EM> feature, and portable <EM>termcap</EM> ap- ++ With terminfo support, <STRONG>tgoto</STRONG> is able to use some of the terminfo ++ features, but not all. In particular, it allows only numeric pa- ++ rameters; <STRONG>tparm</STRONG> supports string parameters. ++ ++ However, <STRONG>tparm</STRONG> is not a <EM>termcap</EM> feature, and portable <EM>termcap</EM> ap- + plications should not rely upon its availability. + +- The <STRONG>tputs</STRONG> routine is described on the <STRONG><A HREF="curs_terminfo.3x.html">curs_terminfo(3x)</A></STRONG> manual page. ++ The <STRONG>tputs</STRONG> routine is described on the <STRONG><A HREF="curs_terminfo.3x.html">curs_terminfo(3x)</A></STRONG> manual page. + It can retrieve capabilities by either termcap or terminfo name. + + + </PRE><H3><a name="h3-Global-Variables">Global Variables</a></H3><PRE> +- The variables <STRONG>PC</STRONG>, <STRONG>UP</STRONG> and <STRONG>BC</STRONG> are set by <STRONG>tgetent</STRONG> to the terminfo entry's ++ The variables <STRONG>PC</STRONG>, <STRONG>UP</STRONG> and <STRONG>BC</STRONG> are set by <STRONG>tgetent</STRONG> to the terminfo entry's + data for <STRONG>pad_char</STRONG>, <STRONG>cursor_up</STRONG> and <STRONG>backspace_if_not_bs</STRONG>, respectively. <STRONG>UP</STRONG> +- is not used by ncurses. <STRONG>PC</STRONG> is used in the <STRONG>tdelay_output</STRONG> function. <STRONG>BC</STRONG> +- is used in the <STRONG>tgoto</STRONG> emulation. The variable <STRONG>ospeed</STRONG> is set by ncurses ++ is not used by ncurses. <STRONG>PC</STRONG> is used in the <STRONG>tdelay_output</STRONG> function. <STRONG>BC</STRONG> ++ is used in the <STRONG>tgoto</STRONG> emulation. The variable <STRONG>ospeed</STRONG> is set by ncurses + in a system-specific coding to reflect the terminal speed. + + + </PRE><H3><a name="h3-Releasing-Memory">Releasing Memory</a></H3><PRE> +- The termcap functions provide no means for freeing memory, because +- legacy termcap implementations used only the buffer areas provided by +- the caller via <STRONG>tgetent</STRONG> and <STRONG>tgetstr</STRONG>. Those buffers are unused in ter- ++ The termcap functions provide no means for freeing memory, because ++ legacy termcap implementations used only the buffer areas provided by ++ the caller via <STRONG>tgetent</STRONG> and <STRONG>tgetstr</STRONG>. Those buffers are unused in ter- + minfo. + + On the other hand, terminfo allocates memory. It uses <STRONG>setupterm</STRONG> to re- +@@ -178,41 +183,55 @@ + <STRONG>del_curterm(cur_term);</STRONG> + + +- to free this memory, but there is an additional complication with +- ncurses. It uses a fixed-size <EM>pool</EM> of storage locations, one per set- +- ting of the <STRONG>TERM</STRONG> variable when <STRONG>tgetent</STRONG> is called. The <STRONG>screen(1)</STRONG> pro- ++ to free this memory, but there is an additional complication with ++ ncurses. It uses a fixed-size <EM>pool</EM> of storage locations, one per set- ++ ting of the <STRONG>TERM</STRONG> variable when <STRONG>tgetent</STRONG> is called. The <STRONG>screen(1)</STRONG> pro- + gram relies upon this arrangement, to improve its performance. + +- An application which uses only the low-level termcap functions could ++ An application which uses only the low-level termcap functions could + free the memory using <STRONG>del_curterm</STRONG>, because the pool is freed using oth- + er functions (see <STRONG><A HREF="curs_memleaks.3x.html">curs_memleaks(3x)</A></STRONG>). + + + </PRE><H2><a name="h2-RETURN-VALUE">RETURN VALUE</a></H2><PRE> +- Except where explicitly noted, routines that return an integer return +- <STRONG>ERR</STRONG> upon failure and <STRONG>OK</STRONG> (SVr4 only specifies "an integer value other ++ Except where explicitly noted, routines that return an integer return ++ <STRONG>ERR</STRONG> upon failure and <STRONG>OK</STRONG> (SVr4 only specifies "an integer value other + than <STRONG>ERR</STRONG>") upon successful completion. + + Routines that return pointers return <STRONG>NULL</STRONG> on error. + ++ A few special cases apply: ++ ++ <STRONG>o</STRONG> If the terminal database has not been initialized, these return an ++ error. ++ ++ <STRONG>o</STRONG> The calls with a string parameter (<STRONG>tgoto</STRONG>, <STRONG>tputs</STRONG>) check if the ++ string is null, or cancelled. Those return an error. ++ ++ <STRONG>o</STRONG> A call to <STRONG>tgoto</STRONG> using a capability with string parameters is an er- ++ ror. ++ ++ <STRONG>o</STRONG> A call to <STRONG>tgoto</STRONG> using a capability with no parameters, or more than ++ two is an error. ++ + + </PRE><H2><a name="h2-BUGS">BUGS</a></H2><PRE> +- If you call <STRONG>tgetstr</STRONG> to fetch <STRONG>ca</STRONG> or any other parameterized string, be +- aware that it will be returned in terminfo notation, not the older and ++ If you call <STRONG>tgetstr</STRONG> to fetch <STRONG>ca</STRONG> or any other parameterized string, be ++ aware that it will be returned in terminfo notation, not the older and + not-quite-compatible termcap notation. This will not cause problems if +- all you do with it is call <STRONG>tgoto</STRONG> or <STRONG>tparm</STRONG>, which both expand terminfo- +- style strings as terminfo. (The <STRONG>tgoto</STRONG> function, if configured to sup- +- port termcap, will check if the string is indeed terminfo-style by +- looking for "%p" parameters or "$<..>" delays, and invoke a termcap- ++ all you do with it is call <STRONG>tgoto</STRONG> or <STRONG>tparm</STRONG>, which both expand terminfo- ++ style strings as terminfo. (The <STRONG>tgoto</STRONG> function, if configured to sup- ++ port termcap, will check if the string is indeed terminfo-style by ++ looking for "%p" parameters or "$<..>" delays, and invoke a termcap- + style parser if the string does not appear to be terminfo). + +- Because terminfo conventions for representing padding in string capa- ++ Because terminfo conventions for representing padding in string capa- + bilities differ from termcap's, users can be surprised: + + <STRONG>o</STRONG> <STRONG>tputs("50")</STRONG> in a terminfo system will put out a literal "50" rather + than busy-waiting for 50 milliseconds. + +- <STRONG>o</STRONG> However, if ncurses is configured to support termcap, it may also ++ <STRONG>o</STRONG> However, if ncurses is configured to support termcap, it may also + have been configured to support the BSD-style padding. + + In that case, <STRONG>tputs</STRONG> inspects strings passed to it, looking for dig- +@@ -221,9 +240,9 @@ + <STRONG>tputs("50")</STRONG> in a termcap system may wait for 50 milliseconds rather + than put out a literal "50" + +- Note that termcap has nothing analogous to terminfo's <STRONG>sgr</STRONG> string. One +- consequence of this is that termcap applications assume <STRONG>me</STRONG> (terminfo +- <STRONG>sgr0</STRONG>) does not reset the alternate character set. This implementation ++ Note that termcap has nothing analogous to terminfo's <STRONG>sgr</STRONG> string. One ++ consequence of this is that termcap applications assume <STRONG>me</STRONG> (terminfo ++ <STRONG>sgr0</STRONG>) does not reset the alternate character set. This implementation + checks for, and modifies the data shown to the termcap interface to ac- + commodate termcap's limitation in this respect. + +@@ -231,22 +250,22 @@ + </PRE><H2><a name="h2-PORTABILITY">PORTABILITY</a></H2><PRE> + + </PRE><H3><a name="h3-Standards">Standards</a></H3><PRE> +- These functions are provided for supporting legacy applications, and ++ These functions are provided for supporting legacy applications, and + should not be used in new programs: + + <STRONG>o</STRONG> The XSI Curses standard, Issue 4 describes these functions. Howev- +- er, they are marked TO BE WITHDRAWN and may be removed in future ++ er, they are marked TO BE WITHDRAWN and may be removed in future + versions. + + <STRONG>o</STRONG> X/Open Curses, Issue 5 (December 2007) marked the termcap interface + (along with <STRONG>vwprintw</STRONG> and <STRONG>vwscanw</STRONG>) as withdrawn. + +- Neither the XSI Curses standard nor the SVr4 man pages documented the +- return values of <STRONG>tgetent</STRONG> correctly, though all three were in fact re- +- turned ever since SVr1. In particular, an omission in the XSI Curses +- documentation has been misinterpreted to mean that <STRONG>tgetent</STRONG> returns <STRONG>OK</STRONG> +- or <STRONG>ERR</STRONG>. Because the purpose of these functions is to provide compati- +- bility with the <EM>termcap</EM> library, that is a defect in XCurses, Issue 4, ++ Neither the XSI Curses standard nor the SVr4 man pages documented the ++ return values of <STRONG>tgetent</STRONG> correctly, though all three were in fact re- ++ turned ever since SVr1. In particular, an omission in the XSI Curses ++ documentation has been misinterpreted to mean that <STRONG>tgetent</STRONG> returns <STRONG>OK</STRONG> ++ or <STRONG>ERR</STRONG>. Because the purpose of these functions is to provide compati- ++ bility with the <EM>termcap</EM> library, that is a defect in XCurses, Issue 4, + Version 2 rather than in ncurses. + + +@@ -254,68 +273,68 @@ + External variables are provided for support of certain termcap applica- + tions. However, termcap applications' use of those variables is poorly + documented, e.g., not distinguishing between input and output. In par- +- ticular, some applications are reported to declare and/or modify <STRONG>os-</STRONG> ++ ticular, some applications are reported to declare and/or modify <STRONG>os-</STRONG> + <STRONG>peed</STRONG>. + +- The comment that only the first two characters of the <STRONG>id</STRONG> parameter are ++ The comment that only the first two characters of the <STRONG>id</STRONG> parameter are + used escapes many application developers. The original BSD 4.2 termcap + library (and historical relics thereof) did not require a trailing null +- NUL on the parameter name passed to <STRONG>tgetstr</STRONG>, <STRONG>tgetnum</STRONG> and <STRONG>tgetflag</STRONG>. +- Some applications assume that the termcap interface does not require ++ NUL on the parameter name passed to <STRONG>tgetstr</STRONG>, <STRONG>tgetnum</STRONG> and <STRONG>tgetflag</STRONG>. ++ Some applications assume that the termcap interface does not require + the trailing NUL for the parameter name. Taking into account these is- + sues: + +- <STRONG>o</STRONG> As a special case, <STRONG>tgetflag</STRONG> matched against a single-character +- identifier provided that was at the end of the terminal descrip- ++ <STRONG>o</STRONG> As a special case, <STRONG>tgetflag</STRONG> matched against a single-character ++ identifier provided that was at the end of the terminal descrip- + tion. You should not rely upon this behavior in portable programs. +- This implementation disallows matches against single-character ca- ++ This implementation disallows matches against single-character ca- + pability names. + +- <STRONG>o</STRONG> This implementation disallows matches by the termcap interface ++ <STRONG>o</STRONG> This implementation disallows matches by the termcap interface + against extended capability names which are longer than two charac- + ters. + + The BSD termcap function <STRONG>tgetent</STRONG> returns the text of a termcap entry in +- the buffer passed as an argument. This library (like other terminfo ++ the buffer passed as an argument. This library (like other terminfo + implementations) does not store terminal descriptions as text. It sets + the buffer contents to a null-terminated string. + + + </PRE><H3><a name="h3-Other-Compatibility">Other Compatibility</a></H3><PRE> +- This library includes a termcap.h header, for compatibility with other +- implementations. But the header is rarely used because the other im- ++ This library includes a termcap.h header, for compatibility with other ++ implementations. But the header is rarely used because the other im- + plementations are not strictly compatible. + + The original BSD termcap (through 4.3BSD) had no header file which gave + function prototypes, because that was a feature of ANSI C. BSD termcap +- was written several years before C was standardized. However, there ++ was written several years before C was standardized. However, there + were two different termcap.h header files in the BSD sources: + +- <STRONG>o</STRONG> One was used internally by the <STRONG>jove</STRONG> editor in 2BSD through 4.4BSD. ++ <STRONG>o</STRONG> One was used internally by the <STRONG>jove</STRONG> editor in 2BSD through 4.4BSD. + It defined global symbols for the termcap variables which it used. + +- <STRONG>o</STRONG> The other appeared in 4.4BSD Lite Release 2 (mid-1993) as part of ++ <STRONG>o</STRONG> The other appeared in 4.4BSD Lite Release 2 (mid-1993) as part of + <EM>libedit</EM> (also known as the <EM>editline</EM> library). The CSRG source his- +- tory shows that this was added in mid-1992. The <EM>libedit</EM> header +- file was used internally, as a convenience for compiling the <EM>edit-</EM> ++ tory shows that this was added in mid-1992. The <EM>libedit</EM> header ++ file was used internally, as a convenience for compiling the <EM>edit-</EM> + <EM>line</EM> library. It declared function prototypes, but no global vari- + ables. + +- The header file from <EM>libedit</EM> was added to NetBSD's termcap library in ++ The header file from <EM>libedit</EM> was added to NetBSD's termcap library in + mid-1994. + +- Meanwhile, GNU termcap was under development, starting in 1990. The +- first release (termcap 1.0) in 1991 included a termcap.h header. The +- second release (termcap 1.1) in September 1992 modified the header to ++ Meanwhile, GNU termcap was under development, starting in 1990. The ++ first release (termcap 1.0) in 1991 included a termcap.h header. The ++ second release (termcap 1.1) in September 1992 modified the header to + use <STRONG>const</STRONG> for the function prototypes in the header where one would ex- +- pect the parameters to be read-only. This was a difference versus the +- original BSD termcap. The prototype for <STRONG>tputs</STRONG> also differed, but in ++ pect the parameters to be read-only. This was a difference versus the ++ original BSD termcap. The prototype for <STRONG>tputs</STRONG> also differed, but in + that instance, it was <EM>libedit</EM> which differed from BSD termcap. + + A copy of GNU termcap 1.3 was bundled with <EM>bash</EM> in mid-1993, to support + the <STRONG>readline(3)</STRONG> library. + +- A termcap.h file was provided in ncurses 1.8.1 (November 1993). That ++ A termcap.h file was provided in ncurses 1.8.1 (November 1993). That + reflected influence by <STRONG>emacs(1)</STRONG> (rather than <STRONG>jove(1)</STRONG>) and GNU termcap: + + <STRONG>o</STRONG> it provided declarations for a few global symbols used by <STRONG>emacs</STRONG> +@@ -325,8 +344,8 @@ + <STRONG>o</STRONG> a prototype for <STRONG>tparam</STRONG> (a GNU termcap feature) was provided. + + Later (in mid-1996) the <STRONG>tparam</STRONG> function was removed from ncurses. As a +- result, there are differences between any of the four implementations, +- which must be taken into account by programs which can work with all ++ result, there are differences between any of the four implementations, ++ which must be taken into account by programs which can work with all + termcap library interfaces. + + +diff --git a/doc/html/man/curs_terminfo.3x.html b/doc/html/man/curs_terminfo.3x.html +index c50d7db3..480cafce 100644 +--- a/doc/html/man/curs_terminfo.3x.html ++++ b/doc/html/man/curs_terminfo.3x.html +@@ -1,6 +1,6 @@ + <!-- + **************************************************************************** +- * Copyright 2018-2022,2022 Thomas E. Dickey * ++ * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -27,7 +27,7 @@ + * sale, use or other dealings in this Software without prior written * + * authorization. * + **************************************************************************** +- * @Id: curs_terminfo.3x,v 1.82 2022/06/04 22:47:05 tom Exp @ ++ * @Id: curs_terminfo.3x,v 1.83 2023/04/08 22:54:21 tom Exp @ + * *************************************************************************** + * *************************************************************************** + * *************************************************************************** +@@ -83,6 +83,9 @@ + <STRONG>int</STRONG> <STRONG>restartterm(const</STRONG> <STRONG>char</STRONG> <STRONG>*</STRONG><EM>term</EM><STRONG>,</STRONG> <STRONG>int</STRONG> <EM>filedes</EM><STRONG>,</STRONG> <STRONG>int</STRONG> <STRONG>*</STRONG><EM>errret</EM><STRONG>);</STRONG> + + <STRONG>char</STRONG> <STRONG>*tparm(const</STRONG> <STRONG>char</STRONG> <STRONG>*</STRONG><EM>str</EM><STRONG>,</STRONG> <STRONG>...);</STRONG> ++ <EM>or</EM> ++ <STRONG>char</STRONG> <STRONG>*tparm(const</STRONG> <STRONG>char</STRONG> <STRONG>*</STRONG><EM>str</EM><STRONG>,</STRONG> <STRONG>long</STRONG> <EM>p1</EM> <EM>...</EM> <STRONG>long</STRONG> <EM>p9</EM><STRONG>);</STRONG> ++ + <STRONG>int</STRONG> <STRONG>tputs(const</STRONG> <STRONG>char</STRONG> <STRONG>*</STRONG><EM>str</EM><STRONG>,</STRONG> <STRONG>int</STRONG> <EM>affcnt</EM><STRONG>,</STRONG> <STRONG>int</STRONG> <STRONG>(*</STRONG><EM>putc</EM><STRONG>)(int));</STRONG> + <STRONG>int</STRONG> <STRONG>putp(const</STRONG> <STRONG>char</STRONG> <STRONG>*</STRONG><EM>str</EM><STRONG>);</STRONG> + +@@ -398,6 +401,11 @@ + the initial windows (stdscr, curscr, newscr). Other error con- + ditions are documented above. + ++ <STRONG>tparm</STRONG> ++ returns a null if the capability would require unexpected pa- ++ rameters, e.g., too many, too few, or incorrect types (strings ++ where integers are expected, or vice versa). ++ + <STRONG>tputs</STRONG> + returns an error if the string parameter is null. It does not + detect I/O errors: X/Open states that <STRONG>tputs</STRONG> ignores the return +@@ -466,7 +474,6 @@ + <STRONG>Function</STRONG> <STRONG>Description</STRONG> + ------------------------------------------- + tigetflag get boolean entry for given <EM>id</EM> +- + tigetnum get numeric entry for given <EM>id</EM> + tigetstr get string entry for given <EM>id</EM> + +@@ -568,6 +575,34 @@ + In response to review comments by Thomas E. Dickey, X/Open Curses + Issue 7 proposed the <STRONG>tiparm</STRONG> function in mid-2009. + ++ While <STRONG>tiparm</STRONG> is always provided in ncurses, the older form is only ++ available as a build-time configuration option. If not specially ++ configured, <STRONG>tparm</STRONG> is the same as <STRONG>tiparm</STRONG>. ++ ++ Both forms of <STRONG>tparm</STRONG> have drawbacks: ++ ++ <STRONG>o</STRONG> Most of the calls to <STRONG>tparm</STRONG> use only one or two parameters. Passing ++ nine on each call is awkward. ++ ++ Using <STRONG>long</STRONG> for the numeric parameter type is a workaround to make ++ the parameter use the same amount of stack as a pointer. That ap- ++ proach dates back to the mid-1980s, before C was standarized. ++ Since then, there is a standard (and pointers are not required to ++ fit in a long). ++ ++ <STRONG>o</STRONG> Providing the right number of parameters for a variadic function ++ such as <STRONG>tiparm</STRONG> can be a problem, in particular for string parame- ++ ters. However, only a few terminfo capabilities use string parame- ++ ters (e.g., the ones used for programmable function keys). ++ ++ The ncurses library checks usage of these capabilities, and returns ++ an error if the capability mishandles string parameters. But it ++ cannot check if a calling program provides strings in the right ++ places for the <STRONG>tparm</STRONG> calls. ++ ++ The <STRONG><A HREF="tput.3x.html">tput(3x)</A></STRONG> program checks its use of these capabilities with a ++ table, so that it calls <STRONG>tparm</STRONG> correctly. ++ + + </PRE><H3><a name="h3-Special-TERM-treatment">Special TERM treatment</a></H3><PRE> + If configured to use the terminal-driver, e.g., for the MinGW port, +diff --git a/doc/html/man/form.3x.html b/doc/html/man/form.3x.html +index 422171c8..9551b458 100644 +--- a/doc/html/man/form.3x.html ++++ b/doc/html/man/form.3x.html +@@ -248,7 +248,7 @@ + <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG> and related pages whose names begin "form_" for detailed + descriptions of the entry points. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/infocmp.1m.html b/doc/html/man/infocmp.1m.html +index 81b95ac5..a72af34b 100644 +--- a/doc/html/man/infocmp.1m.html ++++ b/doc/html/man/infocmp.1m.html +@@ -514,7 +514,7 @@ + + https://invisible-island.net/ncurses/tctest.html + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H2><a name="h2-AUTHOR">AUTHOR</a></H2><PRE> +diff --git a/doc/html/man/infotocap.1m.html b/doc/html/man/infotocap.1m.html +index 1ea690cb..1ab52071 100644 +--- a/doc/html/man/infotocap.1m.html ++++ b/doc/html/man/infotocap.1m.html +@@ -91,7 +91,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="infocmp.1m.html">infocmp(1m)</A></STRONG>, <STRONG><A HREF="tic.1m.html">tic(1m)</A></STRONG>, <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG> + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H2><a name="h2-AUTHOR">AUTHOR</a></H2><PRE> +diff --git a/doc/html/man/menu.3x.html b/doc/html/man/menu.3x.html +index a8f2c961..8f4641bf 100644 +--- a/doc/html/man/menu.3x.html ++++ b/doc/html/man/menu.3x.html +@@ -223,7 +223,7 @@ + <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG> and related pages whose names begin "menu_" for detailed + descriptions of the entry points. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/ncurses.3x.html b/doc/html/man/ncurses.3x.html +index ab2b69d1..9cf27bf5 100644 +--- a/doc/html/man/ncurses.3x.html ++++ b/doc/html/man/ncurses.3x.html +@@ -60,7 +60,7 @@ + method of updating character screens with reasonable optimization. + This implementation is "new curses" (ncurses) and is the approved + replacement for 4.4BSD classic curses, which has been discontinued. +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + The <STRONG>ncurses</STRONG> library emulates the curses library of System V Release 4 + UNIX, and XPG4 (X/Open Portability Guide) curses (also known as XSI +diff --git a/doc/html/man/ncurses6-config.1.html b/doc/html/man/ncurses6-config.1.html +index 0f64e3de..9cd27f50 100644 +--- a/doc/html/man/ncurses6-config.1.html ++++ b/doc/html/man/ncurses6-config.1.html +@@ -113,7 +113,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG> + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/panel.3x.html b/doc/html/man/panel.3x.html +index 761a0fbd..0fd84723 100644 +--- a/doc/html/man/panel.3x.html ++++ b/doc/html/man/panel.3x.html +@@ -281,7 +281,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, <STRONG><A HREF="curs_variables.3x.html">curs_variables(3x)</A></STRONG>, + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H2><a name="h2-AUTHOR">AUTHOR</a></H2><PRE> +diff --git a/doc/html/man/tabs.1.html b/doc/html/man/tabs.1.html +index 3e9f0f9d..228e17d8 100644 +--- a/doc/html/man/tabs.1.html ++++ b/doc/html/man/tabs.1.html +@@ -252,7 +252,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="infocmp.1m.html">infocmp(1m)</A></STRONG>, <STRONG><A HREF="tset.1.html">tset(1)</A></STRONG>, <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/terminfo.5.html b/doc/html/man/terminfo.5.html +index 23b27bfb..88986bf7 100644 +--- a/doc/html/man/terminfo.5.html ++++ b/doc/html/man/terminfo.5.html +@@ -106,7 +106,7 @@ + have, by specifying how to perform screen operations, and by specifying + padding requirements and initialization sequences. + +- This manual describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This manual describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H3><a name="h3-Terminfo-Entry-Syntax">Terminfo Entry Syntax</a></H3><PRE> +diff --git a/doc/html/man/tic.1m.html b/doc/html/man/tic.1m.html +index cced3343..6c12f037 100644 +--- a/doc/html/man/tic.1m.html ++++ b/doc/html/man/tic.1m.html +@@ -469,7 +469,7 @@ + <STRONG><A HREF="captoinfo.1m.html">captoinfo(1m)</A></STRONG>, <STRONG><A HREF="infocmp.1m.html">infocmp(1m)</A></STRONG>, <STRONG><A HREF="infotocap.1m.html">infotocap(1m)</A></STRONG>, <STRONG><A HREF="toe.1m.html">toe(1m)</A></STRONG>, <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, + <STRONG><A HREF="term.5.html">term(5)</A></STRONG>. <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>. <STRONG><A HREF="user_caps.5.html">user_caps(5)</A></STRONG>. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + </PRE><H2><a name="h2-AUTHOR">AUTHOR</a></H2><PRE> +diff --git a/doc/html/man/toe.1m.html b/doc/html/man/toe.1m.html +index a9151184..38859624 100644 +--- a/doc/html/man/toe.1m.html ++++ b/doc/html/man/toe.1m.html +@@ -171,7 +171,7 @@ + <STRONG><A HREF="captoinfo.1m.html">captoinfo(1m)</A></STRONG>, <STRONG><A HREF="infocmp.1m.html">infocmp(1m)</A></STRONG>, <STRONG><A HREF="infotocap.1m.html">infotocap(1m)</A></STRONG>, <STRONG><A HREF="tic.1m.html">tic(1m)</A></STRONG>, <STRONG><A HREF="ncurses.3x.html">curses(3x)</A></STRONG>, + <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/tput.1.html b/doc/html/man/tput.1.html +index 6a330a55..ee231640 100644 +--- a/doc/html/man/tput.1.html ++++ b/doc/html/man/tput.1.html +@@ -545,7 +545,7 @@ + </PRE><H2><a name="h2-SEE-ALSO">SEE ALSO</a></H2><PRE> + <STRONG><A HREF="clear.1.html">clear(1)</A></STRONG>, <STRONG>stty(1)</STRONG>, <STRONG><A HREF="tabs.1.html">tabs(1)</A></STRONG>, <STRONG><A HREF="tset.1.html">tset(1)</A></STRONG>, <STRONG><A HREF="curs_termcap.3x.html">curs_termcap(3x)</A></STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>. + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/doc/html/man/tset.1.html b/doc/html/man/tset.1.html +index c610a8c8..19396d91 100644 +--- a/doc/html/man/tset.1.html ++++ b/doc/html/man/tset.1.html +@@ -391,7 +391,7 @@ + <STRONG>csh(1)</STRONG>, <STRONG>sh(1)</STRONG>, <STRONG>stty(1)</STRONG>, <STRONG><A HREF="curs_terminfo.3x.html">curs_terminfo(3x)</A></STRONG>, <STRONG>tty(4)</STRONG>, <STRONG><A HREF="terminfo.5.html">terminfo(5)</A></STRONG>, + <STRONG>ttys(5)</STRONG>, <STRONG>environ(7)</STRONG> + +- This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20221231). ++ This describes <STRONG>ncurses</STRONG> version 6.4 (patch 20230408). + + + +diff --git a/man/curs_termcap.3x b/man/curs_termcap.3x +index e073d940..1630658d 100644 +--- a/man/curs_termcap.3x ++++ b/man/curs_termcap.3x +@@ -1,5 +1,5 @@ + .\"*************************************************************************** +-.\" Copyright 2018-2022,2022 Thomas E. Dickey * ++.\" Copyright 2018-2022,2023 Thomas E. Dickey * + .\" Copyright 1998-2017,2018 Free Software Foundation, Inc. * + .\" * + .\" Permission is hereby granted, free of charge, to any person obtaining a * +@@ -27,7 +27,7 @@ + .\" authorization. * + .\"*************************************************************************** + .\" +-.\" $Id: curs_termcap.3x,v 1.56 2022/02/12 20:05:11 tom Exp $ ++.\" $Id: curs_termcap.3x,v 1.57 2023/04/08 21:43:01 tom Exp $ + .TH curs_termcap 3X "" + .ie \n(.g .ds `` \(lq + .el .ds `` `` +@@ -173,7 +173,13 @@ It does this also for calls requiring only a single parameter. + In that case, the first parameter is merely a placeholder. + .bP + Normally the ncurses library is compiled with terminfo support. +-In that case, \fBtgoto\fP uses \fBtparm\fP(3X) (a more capable formatter). ++In that case, \fBtgoto\fP uses an internal version of ++\fBtparm\fP(3X) (a more capable formatter). ++.IP ++With terminfo support, \fBtgoto\fP is able to use some of the terminfo ++features, but not all. ++In particular, it allows only numeric parameters; ++\fBtparm\fP supports string parameters. + .IP + However, \fBtparm\fP is not a \fItermcap\fP feature, + and portable \fItermcap\fP applications should not rely upon its availability. +@@ -229,6 +235,20 @@ routines that return an integer return \fBERR\fP upon failure and \fBOK\fP + completion. + .PP + Routines that return pointers return \fBNULL\fP on error. ++.PP ++A few special cases apply: ++.bP ++If the terminal database has not been initialized, ++these return an error. ++.bP ++The calls with a string parameter (\fBtgoto\fP, \fBtputs\fP) ++check if the string is null, or cancelled. ++Those return an error. ++.bP ++A call to \fBtgoto\fP using a capability with string parameters is an error. ++.bP ++A call to \fBtgoto\fP using a capability with no parameters, ++or more than two is an error. + .SH BUGS + If you call \fBtgetstr\fP to fetch \fBca\fP or any other parameterized string, + be aware that it will be returned in terminfo notation, not the older and +diff --git a/man/curs_terminfo.3x b/man/curs_terminfo.3x +index 00ae1349..5ea01ee6 100644 +--- a/man/curs_terminfo.3x ++++ b/man/curs_terminfo.3x +@@ -1,5 +1,5 @@ + .\"*************************************************************************** +-.\" Copyright 2018-2022,2022 Thomas E. Dickey * ++.\" Copyright 2018-2022,2023 Thomas E. Dickey * + .\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * + .\" * + .\" Permission is hereby granted, free of charge, to any person obtaining a * +@@ -27,7 +27,7 @@ + .\" authorization. * + .\"*************************************************************************** + .\" +-.\" $Id: curs_terminfo.3x,v 1.82 2022/06/04 22:47:05 tom Exp $ ++.\" $Id: curs_terminfo.3x,v 1.83 2023/04/08 22:54:21 tom Exp $ + .TH curs_terminfo 3X "" + .ie \n(.g .ds `` \(lq + .el .ds `` `` +@@ -86,6 +86,10 @@ + .sp + \fBchar *tparm(const char *\fIstr\fB, ...);\fR + .br ++ \fIor\fP ++.br ++\fBchar *tparm(const char *\fIstr\fB, long \fIp1 ... \fBlong \fIp9\fB);\fR ++.sp + \fBint tputs(const char *\fIstr\fB, int \fIaffcnt\fB, int (*\fIputc\fB)(int));\fR + .br + \fBint putp(const char *\fIstr\fB);\fR +@@ -463,6 +467,11 @@ if it cannot allocate enough memory, or + create the initial windows (stdscr, curscr, newscr). + Other error conditions are documented above. + .TP 5 ++\fBtparm\fP ++returns a null if the capability would require unexpected parameters, ++e.g., too many, too few, or incorrect types ++(strings where integers are expected, or vice versa). ++.TP 5 + \fBtputs\fP + returns an error if the string parameter is null. + It does not detect I/O errors: +@@ -663,6 +672,34 @@ zeroes are fine for this purpose. + .IP + In response to review comments by Thomas E. Dickey, + X/Open Curses Issue 7 proposed the \fBtiparm\fP function in mid-2009. ++.IP ++While \fBtiparm\fP is always provided in ncurses, ++the older form is only available as a build-time configuration option. ++If not specially configured, \fBtparm\fP is the same as \fBtiparm\fP. ++.PP ++Both forms of \fBtparm\fP have drawbacks: ++.bP ++Most of the calls to \fBtparm\fP use only one or two parameters. ++Passing nine on each call is awkward. ++.IP ++Using \fBlong\fP for the numeric parameter type is a workaround ++to make the parameter use the same amount of stack as a pointer. ++That approach dates back to the mid-1980s, before C was standarized. ++Since then, there is a standard ++(and pointers are not required to fit in a long). ++.bP ++Providing the right number of parameters for a variadic function ++such as \fBtiparm\fP can be a problem, in particular for string parameters. ++However, only a few terminfo capabilities use string parameters ++(e.g., the ones used for programmable function keys). ++.IP ++The ncurses library checks usage of these capabilities, ++and returns an error if the capability mishandles string parameters. ++But it cannot check if a calling program provides strings in the right ++places for the \fBtparm\fP calls. ++.IP ++The \fBtput\fR(3X) program checks its use of these capabilities with a table, ++so that it calls \fBtparm\fP correctly. + .SS Special TERM treatment + .PP + If configured to use the terminal-driver, +diff --git a/misc/terminfo.src b/misc/terminfo.src +index ef78948a..07713a81 100644 +--- a/misc/terminfo.src ++++ b/misc/terminfo.src +@@ -6,8 +6,8 @@ + # Report bugs and new terminal descriptions to + # bug-ncurses@gnu.org + # +-# $Revision: 1.1041 $ +-# $Date: 2022/12/29 20:11:56 $ ++# $Revision: 1.1057 $ ++# $Date: 2023/04/08 21:08:00 $ + # + # The original header is preserved below for reference. It is noted that there + # is a "newer" version which differs in some cosmetic details (but actually +@@ -7756,7 +7756,7 @@ alacritty+common|base fragment for alacritty, + use=xterm-basic, use=xterm+app, use=ansi+rep, + use=xterm+tmux, use=ecma+strikeout, use=xterm+sl-twm, + use=ecma+italics, use=xterm+pce2, use=xterm+pcc2, +- use=xterm+pcf2, use=bracketed+paste, ++ use=xterm+pcf2, use=bracketed+paste, use=xterm+focus, + + #### Kitty + # https://github.com/kovidgoyal/kitty +@@ -27717,4 +27717,7 @@ v3220|LANPAR Vision II model 3220/3221/3222, + # + correct PS vs PE names in bracketed+paste (report by Bram Moolenaar) + # -TD + # ++# 2023-04-08 ++# + add xterm+focus to alacritty+common (patch by Christian Duerr). ++# + ######## SHANTIH! SHANTIH! SHANTIH! +diff --git a/ncurses/tinfo/lib_tgoto.c b/ncurses/tinfo/lib_tgoto.c +index 9cf5e100..084a322f 100644 +--- a/ncurses/tinfo/lib_tgoto.c ++++ b/ncurses/tinfo/lib_tgoto.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2018-2019,2020 Thomas E. Dickey * ++ * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 2000-2008,2012 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -36,7 +36,7 @@ + #include <ctype.h> + #include <termcap.h> + +-MODULE_ID("$Id: lib_tgoto.c,v 1.21 2020/05/27 23:55:56 tom Exp $") ++MODULE_ID("$Id: lib_tgoto.c,v 1.22 2023/04/08 13:48:58 tom Exp $") + + #if !PURE_TERMINFO + static bool +@@ -207,6 +207,14 @@ tgoto(const char *string, int x, int y) + result = tgoto_internal(string, x, y); + else + #endif +- result = TIPARM_2(string, y, x); ++ if ((result = TIPARM_2(string, y, x)) == NULL) { ++ /* ++ * Because termcap did not provide a more general solution such as ++ * tparm(), it was necessary to handle single-parameter capabilities ++ * using tgoto(). The internal _nc_tiparm() function returns a NULL ++ * for that case; retry for the single-parameter case. ++ */ ++ result = TIPARM_1(string, y); ++ } + returnPtr(result); + } +diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c +index d9bdfd8f..8988a3d4 100644 +--- a/ncurses/tinfo/lib_tparm.c ++++ b/ncurses/tinfo/lib_tparm.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2018-2020,2021 Thomas E. Dickey * ++ * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -53,7 +53,7 @@ + #include <ctype.h> + #include <tic.h> + +-MODULE_ID("$Id: lib_tparm.c,v 1.137 2021/11/20 23:29:15 tom Exp $") ++MODULE_ID("$Id: lib_tparm.c,v 1.141 2023/04/08 18:24:18 tom Exp $") + + /* + * char * +@@ -1086,6 +1086,64 @@ tparam_internal(TPARM_STATE *tps, const char *string, TPARM_DATA *data) + return (TPS(out_buff)); + } + ++#ifdef CUR ++/* ++ * Only a few standard capabilities accept string parameters. The others that ++ * are parameterized accept only numeric parameters. ++ */ ++static bool ++check_string_caps(TPARM_DATA *data, const char *string) ++{ ++ bool result = FALSE; ++ ++#define CHECK_CAP(name) (VALID_STRING(name) && !strcmp(name, string)) ++ ++ /* ++ * Disallow string parameters unless we can check them against a terminal ++ * description. ++ */ ++ if (cur_term != NULL) { ++ int want_type = 0; ++ ++ if (CHECK_CAP(pkey_key)) ++ want_type = 2; /* function key #1, type string #2 */ ++ else if (CHECK_CAP(pkey_local)) ++ want_type = 2; /* function key #1, execute string #2 */ ++ else if (CHECK_CAP(pkey_xmit)) ++ want_type = 2; /* function key #1, transmit string #2 */ ++ else if (CHECK_CAP(plab_norm)) ++ want_type = 2; /* label #1, show string #2 */ ++ else if (CHECK_CAP(pkey_plab)) ++ want_type = 6; /* function key #1, type string #2, show string #3 */ ++#if NCURSES_XNAMES ++ else { ++ char *check; ++ ++ check = tigetstr("Cs"); ++ if (CHECK_CAP(check)) ++ want_type = 1; /* style #1 */ ++ ++ check = tigetstr("Ms"); ++ if (CHECK_CAP(check)) ++ want_type = 3; /* storage unit #1, content #2 */ ++ } ++#endif ++ ++ if (want_type == data->tparm_type) { ++ result = TRUE; ++ } else { ++ T(("unexpected string-parameter")); ++ } ++ } ++ return result; ++} ++ ++#define ValidCap() (myData.tparm_type == 0 || \ ++ check_string_caps(&myData, string)) ++#else ++#define ValidCap() 1 ++#endif ++ + #if NCURSES_TPARM_VARARGS + + NCURSES_EXPORT(char *) +@@ -1100,7 +1158,7 @@ tparm(const char *string, ...) + tps->tname = "tparm"; + #endif /* TRACE */ + +- if (tparm_setup(cur_term, string, &myData) == OK) { ++ if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) { + va_list ap; + + va_start(ap, string); +@@ -1135,7 +1193,7 @@ tparm(const char *string, + tps->tname = "tparm"; + #endif /* TRACE */ + +- if (tparm_setup(cur_term, string, &myData) == OK) { ++ if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) { + + myData.param[0] = a1; + myData.param[1] = a2; +@@ -1166,7 +1224,7 @@ tiparm(const char *string, ...) + tps->tname = "tiparm"; + #endif /* TRACE */ + +- if (tparm_setup(cur_term, string, &myData) == OK) { ++ if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) { + va_list ap; + + va_start(ap, string); +@@ -1179,7 +1237,25 @@ tiparm(const char *string, ...) + } + + /* +- * The internal-use flavor ensures that the parameters are numbers, not strings ++ * The internal-use flavor ensures that parameters are numbers, not strings. ++ * In addition to ensuring that they are numbers, it ensures that the parameter ++ * count is consistent with intended usage. ++ * ++ * Unlike the general-purpose tparm/tiparm, these internal calls are fairly ++ * well defined: ++ * ++ * expected == 0 - not applicable ++ * expected == 1 - set color, or vertical/horizontal addressing ++ * expected == 2 - cursor addressing ++ * expected == 4 - initialize color or color pair ++ * expected == 9 - set attributes ++ * ++ * Only for the last case (set attributes) should a parameter be optional. ++ * Also, a capability which calls for more parameters than expected should be ++ * ignored. ++ * ++ * Return a null if the parameter-checks fail. Otherwise, return a pointer to ++ * the formatted capability string. + */ + NCURSES_EXPORT(char *) + _nc_tiparm(int expected, const char *string, ...) +@@ -1189,22 +1265,36 @@ _nc_tiparm(int expected, const char *string, ...) + char *result = NULL; + + _nc_tparm_err = 0; ++ T((T_CALLED("_nc_tiparm(%d, %s, ...)"), expected, _nc_visbuf(string))); + #ifdef TRACE + tps->tname = "_nc_tiparm"; + #endif /* TRACE */ + +- if (tparm_setup(cur_term, string, &myData) == OK +- && myData.num_actual <= expected +- && myData.tparm_type == 0) { +- va_list ap; ++ if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) { ++ if (myData.num_actual == 0) { ++ T(("missing parameter%s, expected %s%d", ++ expected > 1 ? "s" : "", ++ expected == 9 ? "up to " : "", ++ expected)); ++ } else if (myData.num_actual > expected) { ++ T(("too many parameters, have %d, expected %d", ++ myData.num_actual, ++ expected)); ++ } else if (expected != 9 && myData.num_actual != expected) { ++ T(("expected %d parameters, have %d", ++ myData.num_actual, ++ expected)); ++ } else { ++ va_list ap; + +- va_start(ap, string); +- tparm_copy_valist(&myData, FALSE, ap); +- va_end(ap); ++ va_start(ap, string); ++ tparm_copy_valist(&myData, FALSE, ap); ++ va_end(ap); + +- result = tparam_internal(tps, string, &myData); ++ result = tparam_internal(tps, string, &myData); ++ } + } +- return result; ++ returnPtr(result); + } + + /* +diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c +index 2b1875ed..9c6e9b0e 100644 +--- a/ncurses/tinfo/read_entry.c ++++ b/ncurses/tinfo/read_entry.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2018-2021,2022 Thomas E. Dickey * ++ * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -42,7 +42,7 @@ + + #include <tic.h> + +-MODULE_ID("$Id: read_entry.c,v 1.164 2022/05/08 00:11:44 tom Exp $") ++MODULE_ID("$Id: read_entry.c,v 1.165 2023/04/08 20:14:49 tom Exp $") + + #define MyNumber(n) (short) LOW_MSB(n) + +@@ -323,6 +323,9 @@ _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit) + || bool_count < 0 + || num_count < 0 + || str_count < 0 ++ || bool_count > BOOLCOUNT ++ || num_count > NUMCOUNT ++ || str_count > STRCOUNT + || str_size < 0) { + returnDB(TGETENT_NO); + } +diff --git a/package/ncurses.spec b/package/ncurses.spec +index 72d4e245..a7572864 100644 +--- a/package/ncurses.spec ++++ b/package/ncurses.spec +@@ -1,7 +1,7 @@ + Summary: shared libraries for terminal handling + Name: ncurses6 + Version: 6.4 +-Release: 20221231 ++Release: 20230408 + License: X11 + Group: Development/Libraries + Source: ncurses-%{version}-%{release}.tgz +diff --git a/package/ncursest.spec b/package/ncursest.spec +index 8729842d..f1d073d1 100644 +--- a/package/ncursest.spec ++++ b/package/ncursest.spec +@@ -1,7 +1,7 @@ + Summary: Curses library with POSIX thread support. + Name: ncursest6 + Version: 6.4 +-Release: 20221231 ++Release: 20230408 + License: X11 + Group: Development/Libraries + Source: ncurses-%{version}-%{release}.tgz +diff --git a/progs/tic.c b/progs/tic.c +index 93a0b491..7ae61677 100644 +--- a/progs/tic.c ++++ b/progs/tic.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2018-2021,2022 Thomas E. Dickey * ++ * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2017,2018 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -49,7 +49,7 @@ + #include <parametrized.h> + #include <transform.h> + +-MODULE_ID("$Id: tic.c,v 1.320 2022/09/17 18:55:28 tom Exp $") ++MODULE_ID("$Id: tic.c,v 1.321 2023/04/08 15:51:57 tom Exp $") + + #define STDIN_NAME "<stdin>" + +@@ -2270,9 +2270,15 @@ check_1_infotocap(const char *name, NCURSES_CONST char *value, int count) + + _nc_reset_tparm(NULL); + switch (actual) { ++ case Str: ++ result = TPARM_1(value, strings[1]); ++ break; + case Num_Str: + result = TPARM_2(value, numbers[1], strings[2]); + break; ++ case Str_Str: ++ result = TPARM_2(value, strings[1], strings[2]); ++ break; + case Num_Str_Str: + result = TPARM_3(value, numbers[1], strings[2], strings[3]); + break; +diff --git a/progs/tparm_type.c b/progs/tparm_type.c +index 3da4a077..4fed96a5 100644 +--- a/progs/tparm_type.c ++++ b/progs/tparm_type.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2020 Thomas E. Dickey * ++ * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2014,2015 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -33,7 +33,7 @@ + + #include <tparm_type.h> + +-MODULE_ID("$Id: tparm_type.c,v 1.4 2020/10/24 17:30:32 tom Exp $") ++MODULE_ID("$Id: tparm_type.c,v 1.5 2023/04/08 15:57:01 tom Exp $") + + /* + * Lookup the type of call we should make to tparm(). This ignores the actual +@@ -47,6 +47,7 @@ tparm_type(const char *name) + {code, {longname} }, \ + {code, {ti} }, \ + {code, {tc} } ++#define XD(code, onlyname) TD(code, onlyname, onlyname, onlyname) + TParams result = Numbers; + /* *INDENT-OFF* */ + static const struct { +@@ -58,6 +59,10 @@ tparm_type(const char *name) + TD(Num_Str, "pkey_xmit", "pfx", "px"), + TD(Num_Str, "plab_norm", "pln", "pn"), + TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), ++#if NCURSES_XNAMES ++ XD(Str, "Cs"), ++ XD(Str_Str, "Ms"), ++#endif + }; + /* *INDENT-ON* */ + +@@ -80,12 +85,16 @@ guess_tparm_type(int nparam, char **p_is_s) + case 1: + if (!p_is_s[0]) + result = Numbers; ++ if (p_is_s[0]) ++ result = Str; + break; + case 2: + if (!p_is_s[0] && !p_is_s[1]) + result = Numbers; + if (!p_is_s[0] && p_is_s[1]) + result = Num_Str; ++ if (p_is_s[0] && p_is_s[1]) ++ result = Str_Str; + break; + case 3: + if (!p_is_s[0] && !p_is_s[1] && !p_is_s[2]) +diff --git a/progs/tparm_type.h b/progs/tparm_type.h +index 7c102a30..2f7bd077 100644 +--- a/progs/tparm_type.h ++++ b/progs/tparm_type.h +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2020 Thomas E. Dickey * ++ * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2014 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -32,7 +32,7 @@ + ****************************************************************************/ + + /* +- * $Id: tparm_type.h,v 1.3 2020/10/24 17:11:33 tom Exp $ ++ * $Id: tparm_type.h,v 1.4 2023/04/08 15:41:20 tom Exp $ + * + * determine expected/actual number of parameters to setup for tparm + */ +@@ -45,8 +45,10 @@ + typedef enum { + Other = -1 + ,Numbers = 0 ++ ,Str + ,Num_Str + ,Num_Str_Str ++ ,Str_Str + } TParams; + + extern TParams tparm_type(const char *name); +diff --git a/progs/tput.c b/progs/tput.c +index 4cd0c5ba..41508b72 100644 +--- a/progs/tput.c ++++ b/progs/tput.c +@@ -1,5 +1,5 @@ + /**************************************************************************** +- * Copyright 2018-2021,2022 Thomas E. Dickey * ++ * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * +@@ -47,12 +47,15 @@ + #include <transform.h> + #include <tty_settings.h> + +-MODULE_ID("$Id: tput.c,v 1.99 2022/02/26 23:19:31 tom Exp $") ++MODULE_ID("$Id: tput.c,v 1.102 2023/04/08 16:26:36 tom Exp $") + + #define PUTS(s) fputs(s, stdout) + + const char *_nc_progname = "tput"; + ++static bool opt_v = FALSE; /* quiet, do not show warnings */ ++static bool opt_x = FALSE; /* clear scrollback if possible */ ++ + static bool is_init = FALSE; + static bool is_reset = FALSE; + static bool is_clear = FALSE; +@@ -81,6 +84,7 @@ usage(const char *optstring) + KEEP(" -S << read commands from standard input") + KEEP(" -T TERM use this instead of $TERM") + KEEP(" -V print curses-version") ++ KEEP(" -v verbose, show warnings") + KEEP(" -x do not try to clear scrollback") + KEEP("") + KEEP("Commands:") +@@ -148,7 +152,7 @@ exit_code(int token, int value) + * Returns nonzero on error. + */ + static int +-tput_cmd(int fd, TTY * settings, bool opt_x, int argc, char **argv, int *used) ++tput_cmd(int fd, TTY * settings, int argc, char **argv, int *used) + { + NCURSES_CONST char *name; + char *s; +@@ -231,7 +235,9 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, char **argv, int *used) + } else if (VALID_STRING(s)) { + if (argc > 1) { + int k; ++ int narg; + int analyzed; ++ int provided; + int popcount; + long numbers[1 + NUM_PARM]; + char *strings[1 + NUM_PARM]; +@@ -271,14 +277,45 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, char **argv, int *used) + + popcount = 0; + _nc_reset_tparm(NULL); ++ /* ++ * Count the number of numeric parameters which are provided. ++ */ ++ provided = 0; ++ for (narg = 1; narg < argc; ++narg) { ++ char *ending = NULL; ++ long check = strtol(argv[narg], &ending, 10); ++ if (check < 0 || ending == argv[narg] || *ending != '\0') ++ break; ++ provided = narg; ++ } + switch (paramType) { ++ case Str: ++ s = TPARM_1(s, strings[1]); ++ analyzed = 1; ++ if (provided == 0 && argc >= 1) ++ provided++; ++ break; ++ case Str_Str: ++ s = TPARM_2(s, strings[1], strings[2]); ++ analyzed = 2; ++ if (provided == 0 && argc >= 1) ++ provided++; ++ if (provided == 1 && argc >= 2) ++ provided++; ++ break; + case Num_Str: + s = TPARM_2(s, numbers[1], strings[2]); + analyzed = 2; ++ if (provided == 1 && argc >= 2) ++ provided++; + break; + case Num_Str_Str: + s = TPARM_3(s, numbers[1], strings[2], strings[3]); + analyzed = 3; ++ if (provided == 1 && argc >= 2) ++ provided++; ++ if (provided == 2 && argc >= 3) ++ provided++; + break; + case Numbers: + analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount); +@@ -316,7 +353,13 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, char **argv, int *used) + if (analyzed < popcount) { + analyzed = popcount; + } +- *used += analyzed; ++ if (opt_v && (analyzed != provided)) { ++ fprintf(stderr, "%s: %s parameters for \"%s\"\n", ++ _nc_progname, ++ (analyzed < provided ? "extra" : "missing"), ++ argv[0]); ++ } ++ *used += provided; + } + + /* use putp() in order to perform padding */ +@@ -339,7 +382,6 @@ main(int argc, char **argv) + int used; + TTY old_settings; + TTY tty_settings; +- bool opt_x = FALSE; /* clear scrollback if possible */ + bool is_alias; + bool need_tty; + +@@ -348,7 +390,7 @@ main(int argc, char **argv) + + term = getenv("TERM"); + +- while ((c = getopt(argc, argv, is_alias ? "T:Vx" : "ST:Vx")) != -1) { ++ while ((c = getopt(argc, argv, is_alias ? "T:Vvx" : "ST:Vvx")) != -1) { + switch (c) { + case 'S': + cmdline = FALSE; +@@ -361,6 +403,9 @@ main(int argc, char **argv) + case 'V': + puts(curses_version()); + ExitProgram(EXIT_SUCCESS); ++ case 'v': /* verbose */ ++ opt_v = TRUE; ++ break; + case 'x': /* do not try to clear scrollback */ + opt_x = TRUE; + break; +@@ -404,7 +449,7 @@ main(int argc, char **argv) + usage(NULL); + while (argc > 0) { + tty_settings = old_settings; +- code = tput_cmd(fd, &tty_settings, opt_x, argc, argv, &used); ++ code = tput_cmd(fd, &tty_settings, argc, argv, &used); + if (code != 0) + break; + argc -= used; +@@ -439,7 +484,7 @@ main(int argc, char **argv) + while (argnum > 0) { + int code; + tty_settings = old_settings; +- code = tput_cmd(fd, &tty_settings, opt_x, argnum, argnow, &used); ++ code = tput_cmd(fd, &tty_settings, argnum, argnow, &used); + if (code != 0) { + if (result == 0) + result = ErrSystem(0); /* will return value >4 */ +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-tic-hang.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-tic-hang.patch new file mode 100644 index 000000000..f98a943e5 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0001-tic-hang.patch @@ -0,0 +1,43 @@ +From 168ba7a681be73ac024438e33e14fde1d5aea97d Mon Sep 17 00:00:00 2001 +From: Hongxu Jia <hongxu.jia@windriver.com> +Date: Fri, 30 Mar 2018 10:02:24 +0800 +Subject: [PATCH 1/2] tic hang + +Upstream-Status: Inappropriate [configuration] + +'tic' of some linux distributions (e.g. fedora 11) hang in an infinite +loop when processing the original file. + +Signed-off-by: anonymous + +Rebase to 6.1 +Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> +--- + misc/terminfo.src | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/misc/terminfo.src b/misc/terminfo.src +index 84f4810..6b385ec 100644 +--- a/misc/terminfo.src ++++ b/misc/terminfo.src +@@ -5562,12 +5562,11 @@ konsole-xf3x|KDE console window with keyboard for XFree86 3.x xterm, + # The value for kbs (see konsole-vt100) reflects local customization rather + # than the settings used for XFree86 xterm. + konsole-xf4x|KDE console window with keyboard for XFree86 4.x xterm, +- kend=\EOF, khome=\EOH, use=konsole+pcfkeys, +- use=konsole-vt100, +- +-konsole+pcfkeys|konsole subset of xterm+pcfkeys, +- kcbt=\E[Z, use=xterm+pcc2, use=xterm+pcf0, +- use=xterm+pce2, ++ kend=\EOF, kf1=\EOP, kf13=\EO2P, kf14=\EO2Q, kf15=\EO2R, ++ kf16=\EO2S, kf17=\E[15;2~, kf18=\E[17;2~, kf19=\E[18;2~, ++ kf2=\EOQ, kf20=\E[19;2~, kf21=\E[20;2~, kf22=\E[21;2~, ++ kf23=\E[23;2~, kf24=\E[24;2~, kf3=\EOR, kf4=\EOS, ++ khome=\EOH, use=konsole-vt100, + + # Obsolete: vt100.keymap + # KDE's "vt100" keyboard has no relationship to any terminal that DEC made, but +-- +1.8.3.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-Fix-added-to-mitigate-CVE-2022-29458.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-Fix-added-to-mitigate-CVE-2022-29458.patch deleted file mode 100644 index 1cef2e810..000000000 --- a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-Fix-added-to-mitigate-CVE-2022-29458.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 0ed8a4953f9179d0f077f24779f1cb51c8e9a126 Mon Sep 17 00:00:00 2001 -From: ankita prasad <ankita.prasad@intel.com> -Date: Tue, 12 Jul 2022 17:51:01 +0000 -Subject: [PATCH] Fix added to mitigate CVE-2022-29458 - -ncurses 6.3 before patch 20220416 has an out-of-bounds read -and segmentation violation in convert_strings in tinfo/read_entry.c -in the terminfo library. -The fix is picked from - https://github.com/mirror/ncurses/commit/4c9f63c460cb7134f142aa65f6866c175ed77605 -for the file tinfo/read_entry.c. - -Signed-off-by: Ankita Prasad <ankita.prasad@intel.com> ---- - ncurses/tinfo/read_entry.c | 21 +++++++++++++++++---- - 1 file changed, 17 insertions(+), 4 deletions(-) - -diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c -index 5b570b0f..06c0c437 100644 ---- a/ncurses/tinfo/read_entry.c -+++ b/ncurses/tinfo/read_entry.c -@@ -145,6 +145,7 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table) - { - int i; - char *p; -+ bool corrupt = FALSE; - - for (i = 0; i < count; i++) { - if (IS_NEG1(buf + 2 * i)) { -@@ -154,17 +155,29 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table) - } else if (MyNumber(buf + 2 * i) > size) { - Strings[i] = ABSENT_STRING; - } else { -- Strings[i] = (MyNumber(buf + 2 * i) + table); -- TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i]))); -+ int nn = MyNumber(buf + 2 * i); -+ if (nn >= 0 && nn < size) { -+ Strings[i] = (nn + table); -+ TR(TRACE_DATABASE, ("Strings[%d] = %s", i, -+ _nc_visbuf(Strings[i]))); -+ } else { -+ if (!corrupt) { -+ corrupt = TRUE; -+ TR(TRACE_DATABASE, -+ ("ignore out-of-range index %d to Strings[]", nn)); -+ _nc_warning("corrupt data found in convert_strings"); -+ } -+ Strings[i] = ABSENT_STRING; -+ } - } - - /* make sure all strings are NUL terminated */ - if (VALID_STRING(Strings[i])) { -- for (p = Strings[i]; p <= table + size; p++) -+ for (p = Strings[i]; p < table + size; p++) - if (*p == '\0') - break; - /* if there is no NUL, ignore the string */ -- if (p > table + size) -+ if (p >= table + size) - Strings[i] = ABSENT_STRING; - } - } --- -2.25.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-configure-reproducible.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-configure-reproducible.patch new file mode 100644 index 000000000..66f26c06a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0002-configure-reproducible.patch @@ -0,0 +1,33 @@ +From ec87e53066a9942e9aaba817d71268342f5e83b9 Mon Sep 17 00:00:00 2001 +From: Hongxu Jia <hongxu.jia@windriver.com> +Date: Wed, 16 Aug 2017 14:45:27 +0800 +Subject: [PATCH] configure: reproducible + +"configure" enforces -U for ar flags, breaking deterministic builds. +The flag was added to fix some vaguely specified "recent POSIX binutil +build problems" in 2015. + +Upstream-Status: Pending +Signed-off-by: Juro Bystricky <juro.bystricky@intel.com> + +Rebase to 6.1 + +Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> + +--- + configure | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure b/configure +index 421cf859..a1b7840d 100755 +--- a/configure ++++ b/configure +@@ -5072,7 +5072,7 @@ else + ;; + (*) + cf_cv_ar_flags=unknown +- for cf_ar_flags in -curvU -curv curv -crv crv -cqv cqv -rv rv ++ for cf_ar_flags in -curv curv -crv crv -cqv cqv -rv rv + do + + # check if $ARFLAGS already contains this choice diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch new file mode 100644 index 000000000..a15694d4d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch @@ -0,0 +1,30 @@ +From 10cd0c12a6e14fb4f0498c299c1dd32720b710da Mon Sep 17 00:00:00 2001 +From: Nathan Rossi <nathan@nathanrossi.com> +Date: Mon, 14 Dec 2020 13:39:02 +1000 +Subject: [PATCH] gen-pkgconfig.in: Do not include LDFLAGS in generated pc + files + +Including the LDFLAGS in the pkgconfig output is problematic as OE +includes build host specific paths and options (e.g. uninative and +'-Wl,--dynamic-linker='). + +Upstream-Status: Inappropriate [OE Specific] +Signed-off-by: Nathan Rossi <nathan@nathanrossi.com> + +--- + misc/gen-pkgconfig.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/misc/gen-pkgconfig.in b/misc/gen-pkgconfig.in +index a45dd54f..85273054 100644 +--- a/misc/gen-pkgconfig.in ++++ b/misc/gen-pkgconfig.in +@@ -83,7 +83,7 @@ if [ "$includedir" != "/usr/include" ]; then + fi + + lib_flags= +-for opt in -L$libdir @EXTRA_PKG_LDFLAGS@ @LIBS@ ++for opt in -L$libdir @LIBS@ + do + case $opt in + -l*) # LIBS is handled specially below diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/exit_prototype.patch b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/exit_prototype.patch new file mode 100644 index 000000000..fd961512e --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses/exit_prototype.patch @@ -0,0 +1,32 @@ +From 4a769a441d7e57a23017c3037cde3e53fb9f35fe Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Tue, 30 Aug 2022 15:58:32 -0700 +Subject: [PATCH] Add needed headers for including mbstate_t and exit() + +Upstream-Status: Inappropriate [Reconfigure will solve it] +Signed-off-by: Khem Raj <raj.khem@gmail.com> + +--- + configure | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/configure b/configure +index f377f551..163f8899 100755 +--- a/configure ++++ b/configure +@@ -3423,6 +3423,7 @@ rm -f "conftest.$ac_objext" "conftest.$ac_ext" + cat >"conftest.$ac_ext" <<_ACEOF + #line 3424 "configure" + #include "confdefs.h" ++#include <stdlib.h> + $ac_declaration + int + main (void) +@@ -13111,6 +13112,7 @@ cat >"conftest.$ac_ext" <<_ACEOF + #include <stdlib.h> + #include <stdarg.h> + #include <stdio.h> ++#include <wchar.h> + #ifdef HAVE_LIBUTF8_H + #include <libutf8.h> + #endif diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_%.bbappend deleted file mode 100644 index 7f1ce36c2..000000000 --- a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_%.bbappend +++ /dev/null @@ -1,4 +0,0 @@ -FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" -SRC_URI += "file://0001-Fix-heap-buffer-overflow-in-captoinfo.patch \ - file://0002-Fix-added-to-mitigate-CVE-2022-29458.patch \ - " diff --git a/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_6.4.bb b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_6.4.bb new file mode 100644 index 000000000..c72c3e30e --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/ncurses/ncurses_6.4.bb @@ -0,0 +1,20 @@ +require ncurses.inc + +SRC_URI += "file://0001-tic-hang.patch \ + file://0002-configure-reproducible.patch \ + file://0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch \ + file://exit_prototype.patch \ + " + +#Include CVE mitigation patches. +SRC_URI += "file://0001-patch-20230408-CVE-2023-29491.patch \ + " + +# commit id corresponds to the revision in package version +SRCREV = "79b9071f2be20a24c7be031655a5638f6032f29f" +S = "${WORKDIR}/git" +EXTRA_OECONF += "--with-abi-version=5" +UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+(\.\d+)+)$" + +# This is needed when using patchlevel versions like 6.1+20181013 +#CVE_VERSION = "${@d.getVar("PV").split('+')[0]}.${@d.getVar("PV").split('+')[1]}" diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/CVE-2022-3821.patch b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/CVE-2022-3821.patch new file mode 100644 index 000000000..5e32866f1 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd/CVE-2022-3821.patch @@ -0,0 +1,24 @@ +From 8d2d0895229cfbe39c1c5c16e61e426812a72e8b 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. +--- + 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 +@@ -591,7 +591,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { + t = b; + } + +- n = MIN((size_t) k, l); ++ n = MIN((size_t) k, l-1); + + l -= n; + p += n; diff --git a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend index 262f557e0..66d3a9bdc 100644 --- a/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-core/systemd/systemd_%.bbappend @@ -4,6 +4,7 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" SRC_URI += "file://0002-Add-event-log-for-system-time-synchronization.patch \ file://0003-Added-timeout-to-systemd-networkd-wait-online.servic.patch \ + file://CVE-2022-3821.patch \ " # We don't support loadable modules in kernel config diff --git a/meta-openbmc-mods/meta-common/recipes-devtools/python/python3_%.bbappend b/meta-openbmc-mods/meta-common/recipes-devtools/python/python3_%.bbappend new file mode 100644 index 000000000..4b8688184 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-devtools/python/python3_%.bbappend @@ -0,0 +1,4 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +#Needed for ncurses_6.4 compilation. +DEPENDS += "ncurses" diff --git a/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality/pwquality.conf b/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality/pwquality.conf new file mode 100644 index 000000000..048c0fd7d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality/pwquality.conf @@ -0,0 +1,7 @@ +enforce_for_root +minlen=8 +difok=0 +lcredit=0 +ocredit=0 +dcredit=0 +ucredit=0 diff --git a/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality_%.bbappend new file mode 100644 index 000000000..5c7a6ad5b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/libpwquality/libpwquality_%.bbappend @@ -0,0 +1,15 @@ +EXTRA_OECONF:append = " --enable-python-bindings=no" +EXTRA_OECONF:append = " --with-securedir=${base_libdir}/security" +FILES:${PN} += "${base_libdir}/security/pam_pwquality.so" +RDEPENDS:${PN}:remove:class-target = " ${PYTHON_PN}-core" +RDEPENDS:${PN}-runtime += "libpwquality" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += " \ + file://pwquality.conf \ + " + +do_install:append() { + install -d ${D}/etc/security + install -m 0644 ${WORKDIR}/pwquality.conf ${D}/etc/security +} diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/0001-run-xtests.sh-check-whether-files-exist.patch b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/0001-run-xtests.sh-check-whether-files-exist.patch new file mode 100644 index 000000000..40040a873 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/0001-run-xtests.sh-check-whether-files-exist.patch @@ -0,0 +1,65 @@ +From e8e8ccfd57e0274b431bc5717bf37c488285b07b Mon Sep 17 00:00:00 2001 +From: Mingli Yu <mingli.yu@windriver.com> +Date: Wed, 27 Oct 2021 10:30:46 +0800 +Subject: [PATCH] run-xtests.sh: check whether files exist + +Fixes: + # ./run-xtests.sh . tst-pam_access1 + mv: cannot stat '/etc/security/opasswd': No such file or directory + PASS: tst-pam_access1 + mv: cannot stat '/etc/security/opasswd-pam-xtests': No such file or directory + ================== + 1 tests passed + 0 tests not run + ================== + +Upstream-Status: Backport [https://github.com/linux-pam/linux-pam/commit/e8e8ccfd57e0274b431bc5717bf37c488285b07b] + +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + xtests/run-xtests.sh | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/xtests/run-xtests.sh b/xtests/run-xtests.sh +index 14f585d9..ff9a4dc1 100755 +--- a/xtests/run-xtests.sh ++++ b/xtests/run-xtests.sh +@@ -18,10 +18,12 @@ all=0 + + mkdir -p /etc/security + for config in access.conf group.conf time.conf limits.conf ; do +- cp /etc/security/$config /etc/security/$config-pam-xtests ++ [ -f "/etc/security/$config" ] && ++ mv /etc/security/$config /etc/security/$config-pam-xtests + install -m 644 "${SRCDIR}"/$config /etc/security/$config + done +-mv /etc/security/opasswd /etc/security/opasswd-pam-xtests ++[ -f /etc/security/opasswd ] && ++ mv /etc/security/opasswd /etc/security/opasswd-pam-xtests + + for testname in $XTESTS ; do + for cfg in "${SRCDIR}"/$testname*.pamd ; do +@@ -47,11 +49,15 @@ for testname in $XTESTS ; do + all=`expr $all + 1` + rm -f /etc/pam.d/$testname* + done +-mv /etc/security/access.conf-pam-xtests /etc/security/access.conf +-mv /etc/security/group.conf-pam-xtests /etc/security/group.conf +-mv /etc/security/time.conf-pam-xtests /etc/security/time.conf +-mv /etc/security/limits.conf-pam-xtests /etc/security/limits.conf +-mv /etc/security/opasswd-pam-xtests /etc/security/opasswd ++ ++for config in access.conf group.conf time.conf limits.conf opasswd ; do ++ if [ -f "/etc/security/$config-pam-xtests" ]; then ++ mv /etc/security/$config-pam-xtests /etc/security/$config ++ else ++ rm -f /etc/security/$config ++ fi ++done ++ + if test "$failed" -ne 0; then + echo "===================" + echo "$failed of $all tests failed" +-- +2.32.0 + diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/99_pam b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/99_pam new file mode 100644 index 000000000..a88247be1 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/99_pam @@ -0,0 +1 @@ +d root root 0755 /run/sepermit none diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch new file mode 100644 index 000000000..e7bf03f9f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/CVE-2022-28321-0002.patch @@ -0,0 +1,205 @@ +From 23393bef92c1e768eda329813d7af55481c6ca9f Mon Sep 17 00:00:00 2001 +From: Thorsten Kukuk <kukuk@suse.com> +Date: Thu, 24 Feb 2022 10:37:32 +0100 +Subject: [PATCH 2/2] pam_access: handle hostnames in access.conf + +According to the manual page, the following entry is valid but does not +work: +-:root:ALL EXCEPT localhost + +See https://bugzilla.suse.com/show_bug.cgi?id=1019866 + +Patched is based on PR#226 from Josef Moellers + +Upstream-Status: Backport +CVE: CVE-2022-28321 + +Reference to upstream patch: +[https://github.com/linux-pam/linux-pam/commit/23393bef92c1e768eda329813d7af55481c6ca9f] + +Signed-off-by: Stefan Ghinea <stefan.ghinea@windriver.com> +--- + modules/pam_access/pam_access.c | 95 ++++++++++++++++++++++++++------- + 1 file changed, 76 insertions(+), 19 deletions(-) + +diff --git a/modules/pam_access/pam_access.c b/modules/pam_access/pam_access.c +index 277192b..bca424f 100644 +--- a/modules/pam_access/pam_access.c ++++ b/modules/pam_access/pam_access.c +@@ -637,7 +637,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) + if ((str_len = strlen(string)) > tok_len + && strcasecmp(tok, string + str_len - tok_len) == 0) + return YES; +- } else if (tok[tok_len - 1] == '.') { ++ } else if (tok[tok_len - 1] == '.') { /* internet network numbers (end with ".") */ + struct addrinfo hint; + + memset (&hint, '\0', sizeof (hint)); +@@ -678,7 +678,7 @@ remote_match (pam_handle_t *pamh, char *tok, struct login_info *item) + return NO; + } + +- /* Assume network/netmask with an IP of a host. */ ++ /* Assume network/netmask, IP address or hostname. */ + return network_netmask_match(pamh, tok, string, item); + } + +@@ -696,7 +696,7 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, + /* + * If the token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the string. +- * "NONE" token matches NULL string. ++ * "NONE" token matches NULL string. + */ + + if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ +@@ -714,7 +714,8 @@ string_match (pam_handle_t *pamh, const char *tok, const char *string, + + /* network_netmask_match - match a string against one token + * where string is a hostname or ip (v4,v6) address and tok +- * represents either a single ip (v4,v6) address or a network/netmask ++ * represents either a hostname, a single ip (v4,v6) address ++ * or a network/netmask + */ + static int + network_netmask_match (pam_handle_t *pamh, +@@ -723,10 +724,12 @@ network_netmask_match (pam_handle_t *pamh, + char *netmask_ptr; + char netmask_string[MAXHOSTNAMELEN + 1]; + int addr_type; ++ struct addrinfo *ai = NULL; + + if (item->debug) +- pam_syslog (pamh, LOG_DEBUG, ++ pam_syslog (pamh, LOG_DEBUG, + "network_netmask_match: tok=%s, item=%s", tok, string); ++ + /* OK, check if tok is of type addr/mask */ + if ((netmask_ptr = strchr(tok, '/')) != NULL) + { +@@ -760,54 +763,108 @@ network_netmask_match (pam_handle_t *pamh, + netmask_ptr = number_to_netmask(netmask, addr_type, + netmask_string, MAXHOSTNAMELEN); + } +- } ++ ++ /* ++ * Construct an addrinfo list from the IP address. ++ * This should not fail as the input is a correct IP address... ++ */ ++ if (getaddrinfo (tok, NULL, NULL, &ai) != 0) ++ { ++ return NO; ++ } ++ } + else +- /* NO, then check if it is only an addr */ +- if (isipaddr(tok, NULL, NULL) != YES) ++ { ++ /* ++ * It is either an IP address or a hostname. ++ * Let getaddrinfo sort everything out ++ */ ++ if (getaddrinfo (tok, NULL, NULL, &ai) != 0) + { ++ pam_syslog(pamh, LOG_ERR, "cannot resolve hostname \"%s\"", tok); ++ + return NO; + } ++ netmask_ptr = NULL; ++ } + + if (isipaddr(string, NULL, NULL) != YES) + { +- /* Assume network/netmask with a name of a host. */ + struct addrinfo hint; + ++ /* Assume network/netmask with a name of a host. */ + memset (&hint, '\0', sizeof (hint)); + hint.ai_flags = AI_CANONNAME; + hint.ai_family = AF_UNSPEC; + + if (item->gai_rv != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else if (!item->res && + (item->gai_rv = getaddrinfo (string, NULL, &hint, &item->res)) != 0) ++ { ++ freeaddrinfo(ai); + return NO; ++ } + else + { + struct addrinfo *runp = item->res; ++ struct addrinfo *runp1; + + while (runp != NULL) + { + char buf[INET6_ADDRSTRLEN]; + +- DIAG_PUSH_IGNORE_CAST_ALIGN; +- inet_ntop (runp->ai_family, +- runp->ai_family == AF_INET +- ? (void *) &((struct sockaddr_in *) runp->ai_addr)->sin_addr +- : (void *) &((struct sockaddr_in6 *) runp->ai_addr)->sin6_addr, +- buf, sizeof (buf)); +- DIAG_POP_IGNORE_CAST_ALIGN; ++ if (getnameinfo (runp->ai_addr, runp->ai_addrlen, buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) != 0) ++ { ++ freeaddrinfo(ai); ++ return NO; ++ } + +- if (are_addresses_equal(buf, tok, netmask_ptr)) ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) + { +- return YES; ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ if (runp->ai_family != runp1->ai_family) ++ continue; ++ ++ if (getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST) != 0) ++ { ++ freeaddrinfo(ai); ++ return NO; ++ } ++ ++ if (are_addresses_equal (buf, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } + } + runp = runp->ai_next; + } + } + } + else +- return (are_addresses_equal(string, tok, netmask_ptr)); ++ { ++ struct addrinfo *runp1; ++ ++ for (runp1 = ai; runp1 != NULL; runp1 = runp1->ai_next) ++ { ++ char buf1[INET6_ADDRSTRLEN]; ++ ++ (void) getnameinfo (runp1->ai_addr, runp1->ai_addrlen, buf1, sizeof (buf1), NULL, 0, NI_NUMERICHOST); ++ ++ if (are_addresses_equal(string, buf1, netmask_ptr)) ++ { ++ freeaddrinfo(ai); ++ return YES; ++ } ++ } ++ } ++ ++ freeaddrinfo(ai); + + return NO; + } +-- +2.37.3 + diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.service b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.service new file mode 100644 index 000000000..099a5c6e0 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.service @@ -0,0 +1,10 @@ +[Unit] +Description=Convert PAM config files + +[Service] +RemainAfterExit=yes +Type=oneshot +ExecStart=/usr/bin/convert-pam-configs.sh + +[Install] +WantedBy=multi-user.target diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.sh b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.sh new file mode 100644 index 000000000..f66f40beb --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/convert-pam-configs.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Convert OpenBMC linux-PAM config files + +# Location of config files this script modifies: +# PAM_CONF_DIR - path to the PAM config files +# SECURITY_CONF_DIR - path to the security config files +PAM_CONF_DIR=/etc/pam.d +SECURITY_CONF_DIR=/etc/security + +# Handle common-password: +# Change cracklib to pwquality and handle the minlen parameter +pam_cracklib=$(grep "^password.*pam_cracklib.so" ${PAM_CONF_DIR}/common-password) +if [ -n "${pam_cracklib}" ] +then + echo "Changing ${PAM_CONF_DIR}/common-password to use pam_pwquality.so (was pam_cracklib.so)" >&2 + minlen=$(echo ${pam_cracklib} | sed -e "s/.*minlen=\([[:alnum:]]*\).*/\1/") + echo " Converting parameter minlen=${minlen} to ${SECURITY_CONF_DIR}/pwquality.conf minlen" >&2 + sed -i.bak -e "s/^minlen=.*/minlen=$minlen/" ${SECURITY_CONF_DIR}/pwquality.conf + pwquality='password [success=ok default=die] pam_pwquality.so debug' + sed -i.bak -e "s/^password.*pam_cracklib.so.*/$pwquality/" ${PAM_CONF_DIR}/common-password + echo "# This file was converted by $0" >>${PAM_CONF_DIR}/common-password +fi + +# Handle common-auth: +# Change tally2 to faillock and handle the deny & unlock_time parameters +pam_tally2=$(grep "^auth.*pam_tally2.so" ${PAM_CONF_DIR}/common-auth) +if [ -n "${pam_tally2}" ] +then + echo "Changing ${PAM_CONF_DIR}/common-auth to use pam_faillock.so (was pam_tally2.so)" >&2 + deny=$(echo ${pam_tally2} | sed -e "s/.*deny=\([[:alnum:]]*\).*/\1/") + unlock_time=$(echo ${pam_tally2} | sed -e "s/.*unlock_time=\([[:alnum:]]*\).*/\1/") + # Change faillock.conf parameters + echo " Converting parameter deny=${deny} to ${SECURITY_CONF_DIR}/faillock.conf deny" >&2 + echo " Converting parameter unlock_time=${unlock_time} to ${SECURITY_CONF_DIR}/faillock.conf unlock_time" >&2 + sed -i.bak \ + -e "s/^deny=.*/deny=$deny/" \ + -e "s/^unlock_time=.*/unlock_time=$unlock_time/" \ + ${SECURITY_CONF_DIR}/faillock.conf + # Change pam_tally2 to pam_faillock (changes the overall auth stack) + authfail='auth [default=die] pam_faillock.so authfail' + authsucc='auth sufficient pam_faillock.so authsucc' + sed -i.bak \ + -e "/^auth.*pam_tally2.so.*$/d" \ + -e "/^auth.*pam_deny.so/i $authfail\n$authsucc" \ + ${PAM_CONF_DIR}/common-auth + echo "# This file was converted by $0" >>${PAM_CONF_DIR}/common-auth +fi + diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/faillock.conf b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/faillock.conf new file mode 100644 index 000000000..68a658411 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/faillock.conf @@ -0,0 +1,2 @@ +deny=10 +unlock_time=300 diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/libpam-xtests.patch b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/libpam-xtests.patch new file mode 100644 index 000000000..ea145899b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/libpam-xtests.patch @@ -0,0 +1,37 @@ +This patch is used to create a new sub package libpam-xtests to do more checks. + +Upstream-Status: Pending + +Signed-off-by: Kang Kai <kai.kang@windriver.com> +Index: Linux-PAM-1.3.0/xtests/Makefile.am +=================================================================== +--- Linux-PAM-1.3.0.orig/xtests/Makefile.am ++++ Linux-PAM-1.3.0/xtests/Makefile.am +@@ -7,7 +7,7 @@ AM_CFLAGS = -DLIBPAM_COMPILE -I$(top_src + LDADD = $(top_builddir)/libpam/libpam.la \ + $(top_builddir)/libpam_misc/libpam_misc.la + +-CLEANFILES = *~ $(XTESTS) ++CLEANFILES = *~ + + EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ + tst-pam_dispatch3.pamd tst-pam_dispatch4.pamd \ +@@ -51,3 +51,18 @@ EXTRA_PROGRAMS = $(XTESTS) + + xtests: $(XTESTS) run-xtests.sh + "$(srcdir)"/run-xtests.sh "$(srcdir)" ${XTESTS} ${NOSRCTESTS} ++ ++all: $(XTESTS) ++ ++install: install_xtests ++ ++install_xtests: ++ $(INSTALL) -d $(DESTDIR)$(pkgdatadir)/xtests ++ for file in $(EXTRA_DIST) ; do \ ++ $(INSTALL) $(srcdir)/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \ ++ done ++ for file in $(XTESTS); do \ ++ $(INSTALL) .libs/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \ ++ done ++ ++.PHONY: all install_xtests diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam-volatiles.conf b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam-volatiles.conf new file mode 100644 index 000000000..1263feb03 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam-volatiles.conf @@ -0,0 +1 @@ +d /run/sepermit 0755 root root - - diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-account b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-account new file mode 100644 index 000000000..4ebbca8d4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-account @@ -0,0 +1,27 @@ +# +# /etc/pam.d/common-account - authorization settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the authorization modules that define +# the central access policy for use on the system. The default is to +# only deny service to users whose accounts are expired in /etc/shadow. +# +# As of pam 1.0.1-6, this file is managed by pam-auth-update by default. +# To take advantage of this, it is recommended that you configure any +# local modules either before or after the default block, and use +# pam-auth-update to manage selection of other modules. See +# pam-auth-update(8) for details. +# + +# here are the per-package modules (the "Primary" block) +account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so +# here's the fallback if no module succeeds +account requisite pam_deny.so +# Announce if faillock is blocking access +account required pam_faillock.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +account required pam_permit.so +# and here are more per-package modules (the "Additional" block) +# end of pam-auth-update config diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-auth b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-auth new file mode 100644 index 000000000..c051ab7e6 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-auth @@ -0,0 +1,26 @@ +# +# /etc/pam.d/common-auth - authentication settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the authentication modules that define +# the central authentication scheme for use on the system +# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the +# traditional Unix authentication mechanisms. + +# here are the per-package modules (the "Primary" block) +# Try for local user first, and then try for ldap +auth [success=2 default=ignore] pam_unix.so quiet +-auth [success=1 default=ignore] pam_ldap.so ignore_unknown_user ignore_authinfo_unavail +# Control gets here when no authentication module succeeds. Increment the +# failure tally and return failure status to PAM. +auth [default=die] pam_faillock.so authfail +# Control gets here when authentication succeeds. Check if the user is locked +# out due to consecutive authentication failures and return status accordingly. +auth sufficient pam_faillock.so authsucc +# If authsucc failed, deny access +auth requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +auth required pam_permit.so +# and here are more per-package modules (the "Additional" block) diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-password b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-password new file mode 100644 index 000000000..2fc4011b2 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-password @@ -0,0 +1,27 @@ +# +# /etc/pam.d/common-password - password-related modules common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of modules that define the services to be +# used to change user passwords. The default is pam_unix. + +# Explanation of pam_unix options: +# +# The "sha512" option enables salted SHA512 passwords. Without this option, +# the default is Unix crypt. Prior releases used the option "md5". +# +# See the pam_unix manpage for other options. + +# here are the per-package modules (the "Primary" block) +password [success=ok default=die] pam_pwquality.so debug +password [success=ok default=die] pam_ipmicheck.so spec_grp_name=ipmi use_authtok +password [success=ok ignore=ignore default=die] pam_pwhistory.so debug enforce_for_root remember=0 use_authtok +password [success=ok default=die] pam_unix.so sha512 use_authtok +password [success=1 default=die] pam_ipmisave.so spec_grp_name=ipmi spec_pass_file=/etc/ipmi_pass key_file=/etc/key_file +# here's the fallback if no module succeeds +password requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +password required pam_permit.so +# and here are more per-package modules (the "Additional" block) diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session new file mode 100644 index 000000000..a4a551f71 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session @@ -0,0 +1,19 @@ +# +# /etc/pam.d/common-session - session-related modules common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of modules that define tasks to be performed +# at the start and end of sessions of *any* kind (both interactive and +# non-interactive). +# + +# here are the per-package modules (the "Primary" block) +session [default=1] pam_permit.so +# here's the fallback if no module succeeds +session requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +session required pam_permit.so +# and here are more per-package modules (the "Additional" block) +session required pam_unix.so diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session-noninteractive b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session-noninteractive new file mode 100644 index 000000000..b110bb2b4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/common-session-noninteractive @@ -0,0 +1,19 @@ +# +# /etc/pam.d/common-session-noninteractive - session-related modules +# common to all non-interactive services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of modules that define tasks to be performed +# at the start and end of all non-interactive sessions. +# + +# here are the per-package modules (the "Primary" block) +session [default=1] pam_permit.so +# here's the fallback if no module succeeds +session requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +session required pam_permit.so +# and here are more per-package modules (the "Additional" block) +session required pam_unix.so diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/other b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/other new file mode 100644 index 000000000..ec970ecbe --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/pam.d/other @@ -0,0 +1,24 @@ +# +# /etc/pam.d/other - specify the PAM fallback behaviour +# +# Note that this file is used for any unspecified service; for example +#if /etc/pam.d/cron specifies no session modules but cron calls +#pam_open_session, the session module out of /etc/pam.d/other is +#used. + +# We use pam_warn.so to generate syslog notes that the 'other' +#fallback rules are being used (as a hint to suggest you should setup +#specific PAM rules for the service and aid to debugging). Then to be +#secure, deny access to all services by default. + +auth required pam_warn.so +auth required pam_deny.so + +account required pam_warn.so +account required pam_deny.so + +password required pam_warn.so +password required pam_deny.so + +session required pam_warn.so +session required pam_deny.so diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/run-ptest b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/run-ptest new file mode 100644 index 000000000..9c304aee4 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam/run-ptest @@ -0,0 +1,32 @@ +#! /bin/sh + +cd tests + +export srcdir=. + +failed=0 +all=0 +for f in tst-*; do + "./$f" > /dev/null 2>&1 + case "$?" in + 0) + echo "PASS: $f" + all=$((all + 1)) + ;; + 77) + echo "SKIP: $f" + ;; + *) + echo "FAIL: $f" + failed=$((failed + 1)) + all=$((all + 1)) + ;; + esac +done + +if [ "$failed" -eq 0 ] ; then + echo "All $all tests passed" +else + echo "$failed of $all tests failed" +fi +unset srcdir diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_%.bbappend index 21e1d88ea..65a4d6d68 100644 --- a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_%.bbappend @@ -1,7 +1,75 @@ RDEPENDS:${PN}-runtime += "${MLPREFIX}pam-plugin-localuser-${libpam_suffix}" +RDEPENDS:${PN}-runtime += "${MLPREFIX}pam-plugin-faillock-${libpam_suffix}" +RDEPENDS:${PN}-runtime += "libpwquality" +RDEPENDS:${PN}-runtime:remove = "${MLPREFIX}pam-plugin-cracklib-${libpam_suffix}" +RDEPENDS:${PN}-runtime:remove = "${MLPREFIX}pam-plugin-tally2-${libpam_suffix}" + +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += " file://pam.d/common-password \ + file://pam.d/common-account \ + file://pam.d/common-auth \ + file://pam.d/common-session \ + file://faillock.conf \ + file://convert-pam-configs.service \ + file://convert-pam-configs.sh \ + " + +inherit systemd +SYSTEMD_SERVICE:${PN} += "convert-pam-configs.service" + +FILES:${PN} += "${bindir}/convert-pam-configs.sh \ + ${systemd_system_unitdir}/convert-pam-configs.service \ + " -#Default settings lockout duration to 300 seconds and threshold value to 10 do_install:append() { - sed -i 's/deny=0/deny=10/' ${D}${sysconfdir}/pam.d/common-auth - sed -i 's/unlock_time=0/unlock_time=300/' ${D}${sysconfdir}/pam.d/common-auth + install -d ${D}/etc/security + install -m 0644 ${WORKDIR}/faillock.conf ${D}/etc/security + + install -d ${D}${bindir} + install -m 0755 ${WORKDIR}/convert-pam-configs.sh ${D}${bindir} + + install -d ${D}${systemd_system_unitdir} + install -m 0644 ${WORKDIR}/convert-pam-configs.service ${D}${systemd_system_unitdir} } + +# +# Background: +# 1. Linux-PAM modules tally2 and cracklib were removed in libpam_1.5, +# which prompted OpenBMC to change to the faillock and pwquality modules. +# The PAM config files under /etc/pam.d were changed accordingly. +# 2. OpenBMC implementations store Redfish property values in PAM config files. +# For example, the D-Bus property maxLoginAttemptBeforeLockout is stored in +# /etc/pam.d/common-auth as the pam_tally2.so deny= parameter value. +# 3. The /etc directory is readonly and has a readwrite overlayfs. That +# means when a config file changes, an overlay file is created which hides +# the readonly version. +# +# Problem scenario: +# 1. Begin with a BMC that has a firmware image which has the old PAM +# modules and the old PAM config files which have modified parameters. +# For example, there is an overlay file for /etc/pam.d/common-auth. +# 2. Perform a firmware update to a firmware image which has the new PAM +# modules. The updated image will have not have the old PAM modules. +# It will have the new PAM config files in its readonly file system and +# the old PAM config files in its readwrite overlay. +# 3. Note that PAM authentication will always fail at this point because +# the old PAM config files in the overlay tell PAM to use the old PAM +# modules which are not present on the system. +# +# Two possible recoveries are: +# A. Factory reset the BMC. This will clear the readwrite overlay, +# allowing PAM to use the readonly version. +# B. Convert the old PAM config files to the new style. See below. +# +# Service: The convert-pam-configs.service updates the old-style PAM config +# files on the BMC: it changes uses of the old modules to the new modules +# and carries forward configuration parameters. A key point is that files +# are written to *only* as needed to convert uses of the old modules to the +# new modules. See the conversion tool for details. +# +# This service can be removed when the BMC no longer supports a direct +# firware update path from a version which has the old PAM configs to a +# version which has the new PAM configs. +# +# In case of downgrade, Factory reset is recommended. Current logic in existing +# images won't be able to take care of these settings during downgrade. diff --git a/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_1.5.2.bb b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_1.5.2.bb new file mode 100644 index 000000000..5197f1813 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/pam/libpam_1.5.2.bb @@ -0,0 +1,186 @@ +DISABLE_STATIC = "" +SUMMARY = "Linux-PAM (Pluggable Authentication Modules)" +DESCRIPTION = "Linux-PAM (Pluggable Authentication Modules for Linux), a flexible mechanism for authenticating users" +HOMEPAGE = "https://fedorahosted.org/linux-pam/" +BUGTRACKER = "https://fedorahosted.org/linux-pam/newticket" +SECTION = "base" +# PAM is dual licensed under GPL and BSD. +# /etc/pam.d comes from Debian libpam-runtime in 2009-11 (at that time +# libpam-runtime-1.0.1 is GPL-2.0-or-later), by openembedded +LICENSE = "GPL-2.0-or-later | BSD-3-Clause" +LIC_FILES_CHKSUM = "file://COPYING;md5=7eb5c1bf854e8881005d673599ee74d3 \ + file://libpamc/License;md5=a4da476a14c093fdc73be3c3c9ba8fb3 \ + " + +SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/Linux-PAM-${PV}.tar.xz \ + file://99_pam \ + file://pam.d/common-account \ + file://pam.d/common-auth \ + file://pam.d/common-password \ + file://pam.d/common-session \ + file://pam.d/common-session-noninteractive \ + file://pam.d/other \ + file://libpam-xtests.patch \ + file://0001-run-xtests.sh-check-whether-files-exist.patch \ + file://run-ptest \ + file://pam-volatiles.conf \ + file://CVE-2022-28321-0002.patch \ + " + +SRC_URI[sha256sum] = "e4ec7131a91da44512574268f493c6d8ca105c87091691b8e9b56ca685d4f94d" + +DEPENDS = "bison-native flex-native cracklib libxml2-native virtual/crypt" + +EXTRA_OECONF = "--includedir=${includedir}/security \ + --libdir=${base_libdir} \ + --with-systemdunitdir=${systemd_system_unitdir} \ + --disable-nis \ + --disable-regenerate-docu \ + --disable-doc \ + --disable-prelude" + +CFLAGS:append = " -fPIC " + +S = "${WORKDIR}/Linux-PAM-${PV}" + +inherit autotools gettext pkgconfig systemd ptest github-releases + +PACKAGECONFIG ??= "" +PACKAGECONFIG[audit] = "--enable-audit,--disable-audit,audit," +PACKAGECONFIG[userdb] = "--enable-db=db,--enable-db=no,db," + +PACKAGES += "${PN}-runtime ${PN}-xtests" +FILES:${PN} = "${base_libdir}/lib*${SOLIBS}" +FILES:${PN}-dev += "${base_libdir}/security/*.la ${base_libdir}/*.la ${base_libdir}/lib*${SOLIBSDEV}" +FILES:${PN}-runtime = "${sysconfdir} ${sbindir} ${systemd_system_unitdir}" +FILES:${PN}-xtests = "${datadir}/Linux-PAM/xtests" + +PACKAGES_DYNAMIC += "^${MLPREFIX}pam-plugin-.*" + +def get_multilib_bit(d): + baselib = d.getVar('baselib') or '' + return baselib.replace('lib', '') + +libpam_suffix = "suffix${@get_multilib_bit(d)}" + +RPROVIDES:${PN} += "${PN}-${libpam_suffix}" +RPROVIDES:${PN}-runtime += "${PN}-runtime-${libpam_suffix}" + +RDEPENDS:${PN}-runtime = "${PN}-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-deny-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-permit-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-warn-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-unix-${libpam_suffix} \ + " +RDEPENDS:${PN}-xtests = "${PN}-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-access-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-debug-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-pwhistory-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-succeed-if-${libpam_suffix} \ + ${MLPREFIX}pam-plugin-time-${libpam_suffix} \ + bash coreutils" + +# FIXME: Native suffix breaks here, disable it for now +RRECOMMENDS:${PN} = "${PN}-runtime-${libpam_suffix}" +RRECOMMENDS:${PN}:class-native = "" + +python populate_packages:prepend () { + def pam_plugin_hook(file, pkg, pattern, format, basename): + pn = d.getVar('PN') + libpam_suffix = d.getVar('libpam_suffix') + + rdeps = d.getVar('RDEPENDS:' + pkg) + if rdeps: + rdeps = rdeps + " " + pn + "-" + libpam_suffix + else: + rdeps = pn + "-" + libpam_suffix + d.setVar('RDEPENDS:' + pkg, rdeps) + + provides = d.getVar('RPROVIDES:' + pkg) + if provides: + provides = provides + " " + pkg + "-" + libpam_suffix + else: + provides = pkg + "-" + libpam_suffix + d.setVar('RPROVIDES:' + pkg, provides) + + mlprefix = d.getVar('MLPREFIX') or '' + dvar = d.expand('${WORKDIR}/package') + pam_libdir = d.expand('${base_libdir}/security') + pam_sbindir = d.expand('${sbindir}') + pam_filterdir = d.expand('${base_libdir}/security/pam_filter') + pam_pkgname = mlprefix + 'pam-plugin%s' + + do_split_packages(d, pam_libdir, r'^pam(.*)\.so$', pam_pkgname, + 'PAM plugin for %s', hook=pam_plugin_hook, extra_depends='') + do_split_packages(d, pam_filterdir, r'^(.*)$', 'pam-filter-%s', 'PAM filter for %s', extra_depends='') +} + +do_compile_ptest() { + cd tests + sed -i -e 's/$(MAKE) $(AM_MAKEFLAGS) check-TESTS//' Makefile + oe_runmake check-am + cd - +} + +do_install() { + autotools_do_install + + # don't install /var/run when populating rootfs. Do it through volatile + rm -rf ${D}${localstatedir} + + if ${@bb.utils.contains('DISTRO_FEATURES','sysvinit','false','true',d)}; then + rm -rf ${D}${sysconfdir}/init.d/ + rm -rf ${D}${sysconfdir}/rc* + install -d ${D}${sysconfdir}/tmpfiles.d + install -m 0644 ${WORKDIR}/pam-volatiles.conf \ + ${D}${sysconfdir}/tmpfiles.d/pam.conf + else + install -d ${D}${sysconfdir}/default/volatiles + install -m 0644 ${WORKDIR}/99_pam \ + ${D}${sysconfdir}/default/volatiles/ + fi + + install -d ${D}${sysconfdir}/pam.d/ + install -m 0644 ${WORKDIR}/pam.d/* ${D}${sysconfdir}/pam.d/ + + # The lsb requires unix_chkpwd has setuid permission + chmod 4755 ${D}${sbindir}/unix_chkpwd + + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + echo "session optional pam_systemd.so" >> ${D}${sysconfdir}/pam.d/common-session + fi + if ${@bb.utils.contains('DISTRO_FEATURES','usrmerge','false','true',d)}; then + install -d ${D}/${libdir}/ + mv ${D}/${base_libdir}/pkgconfig ${D}/${libdir}/ + fi +} + +do_install_ptest() { + if [ ${PTEST_ENABLED} = "1" ]; then + mkdir -p ${D}${PTEST_PATH}/tests + install -m 0755 ${B}/tests/.libs/* ${D}${PTEST_PATH}/tests + install -m 0644 ${S}/tests/confdir ${D}${PTEST_PATH}/tests + fi +} + +pkg_postinst:${PN}() { + if [ -z "$D" ] && [ -e /etc/init.d/populate-volatile.sh ] ; then + /etc/init.d/populate-volatile.sh update + fi +} + +inherit features_check +REQUIRED_DISTRO_FEATURES = "pam" + +BBCLASSEXTEND = "nativesdk native" + +CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-session" +CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-auth" +CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-password" +CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-session-noninteractive" +CONFFILES:${PN}-runtime += "${sysconfdir}/pam.d/common-account" +CONFFILES:${PN}-runtime += "${sysconfdir}/security/limits.conf" + +GITHUB_BASE_URI = "https://github.com/linux-pam/linux-pam/releases" + +CVE_PRODUCT = "linux-pam" diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/CVE-2022-24903.patch b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/CVE-2022-24903.patch new file mode 100644 index 000000000..f7d70352b --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog/CVE-2022-24903.patch @@ -0,0 +1,164 @@ +From d59de97be98ab70ee38d9efa11d04d8015e23df6 Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards <rgerhards@adiscon.com> +Date: Fri, 22 Apr 2022 09:49:46 +0200 +Subject: [PATCH 1/2] net bugfix: potential buffer overrun + +--- + contrib/imhttp/imhttp.c | 4 +++- + plugins/imptcp/imptcp.c | 4 +++- + runtime/tcps_sess.c | 4 +++- + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/contrib/imhttp/imhttp.c b/contrib/imhttp/imhttp.c +index f09260b586..95704af985 100644 +--- a/contrib/imhttp/imhttp.c ++++ b/contrib/imhttp/imhttp.c +@@ -487,7 +487,9 @@ processOctetMsgLen(const instanceConf_t *const inst, struct conn_wrkr_s *connWrk + connWrkr->parseState.iOctetsRemain = connWrkr->parseState.iOctetsRemain * 10 + ch - '0'; + } + // temporarily save this character into the message buffer +- connWrkr->pMsg[connWrkr->iMsg++] = ch; ++ if(connWrkr->iMsg + 1 < s_iMaxLine) { ++ connWrkr->pMsg[connWrkr->iMsg++] = ch; ++ } + } else { + const char *remoteAddr = ""; + if (connWrkr->propRemoteAddr) { +diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c +index 2df46a236c..c32dec5851 100644 +--- a/plugins/imptcp/imptcp.c ++++ b/plugins/imptcp/imptcp.c +@@ -1107,7 +1107,9 @@ processDataRcvd(ptcpsess_t *const __restrict__ pThis, + if(pThis->iOctetsRemain <= 200000000) { + pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0'; + } +- *(pThis->pMsg + pThis->iMsg++) = c; ++ if(pThis->iMsg < iMaxLine) { ++ *(pThis->pMsg + pThis->iMsg++) = c; ++ } + } else { /* done with the octet count, so this must be the SP terminator */ + DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); + prop.GetString(pThis->peerName, &propPeerName, &lenPeerName); +diff --git a/runtime/tcps_sess.c b/runtime/tcps_sess.c +index 0efa2c23c4..c5442f7638 100644 +--- a/runtime/tcps_sess.c ++++ b/runtime/tcps_sess.c +@@ -390,7 +390,9 @@ processDataRcvd(tcps_sess_t *pThis, + if(pThis->iOctetsRemain <= 200000000) { + pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0'; + } +- *(pThis->pMsg + pThis->iMsg++) = c; ++ if(pThis->iMsg < iMaxLine) { ++ *(pThis->pMsg + pThis->iMsg++) = c; ++ } + } else { /* done with the octet count, so this must be the SP terminator */ + DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); + prop.GetString(pThis->fromHost, &propPeerName, &lenPeerName); + +From 30ccf7cd4c00bfc38c2e0b1461b799b1a412d7fb Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards <rgerhards@adiscon.com> +Date: Mon, 25 Apr 2022 10:18:46 +0200 +Subject: [PATCH 2/2] testbench: new tests for potential buffer overrun + +--- + tests/Makefile.am | 4 ++++ + tests/imptcp-octet-framing-too-long-vg.sh | 23 +++++++++++++++++++++++ + tests/imtcp-octet-framing-too-long-vg.sh | 23 +++++++++++++++++++++++ + 3 files changed, 50 insertions(+) + create mode 100755 tests/imptcp-octet-framing-too-long-vg.sh + create mode 100755 tests/imtcp-octet-framing-too-long-vg.sh + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 330546890e..805949ec8b 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -283,6 +283,7 @@ TESTS += \ + allowed-sender-tcp-fail.sh \ + allowed-sender-tcp-hostname-ok.sh \ + allowed-sender-tcp-hostname-fail.sh \ ++ imtcp-octet-framing-too-long-vg.sh \ + imtcp-discard-truncated-msg.sh \ + imtcp-basic.sh \ + imtcp-basic-hup.sh \ +@@ -1074,6 +1075,7 @@ if ENABLE_IMPTCP + # need to be disabled if we do not have this module + TESTS += \ + manyptcp.sh \ ++ imptcp-octet-framing-too-long-vg.sh \ + imptcp_framing_regex.sh \ + imptcp_framing_regex-oversize.sh \ + imptcp_large.sh \ +@@ -2121,6 +2123,7 @@ EXTRA_DIST= \ + mmjsonparse_simple.sh \ + mmjsonparse-invalid-containerName.sh \ + wtpShutdownAll-assertionFailure.sh \ ++ imptcp-octet-framing-too-long-vg.sh \ + imptcp-oversize-message-display.sh \ + imptcp-msg-truncation-on-number.sh \ + imptcp-msg-truncation-on-number2.sh \ +@@ -2199,6 +2202,7 @@ EXTRA_DIST= \ + allowed-sender-tcp-fail.sh \ + allowed-sender-tcp-hostname-ok.sh \ + allowed-sender-tcp-hostname-fail.sh \ ++ imtcp-octet-framing-too-long-vg.sh \ + imtcp-discard-truncated-msg.sh \ + imtcp-basic.sh \ + imtcp-basic-hup.sh \ +diff --git a/tests/imptcp-octet-framing-too-long-vg.sh b/tests/imptcp-octet-framing-too-long-vg.sh +new file mode 100755 +index 0000000000..d5b2c9adce +--- /dev/null ++++ b/tests/imptcp-octet-framing-too-long-vg.sh +@@ -0,0 +1,23 @@ ++#!/bin/bash ++# added 2022-04-25 by RGerhards, released under ASL 2.0 ++. ${srcdir:=.}/diag.sh init ++generate_conf ++add_conf ' ++$MaxMessageSize 128 ++global(processInternalMessages="on" ++ oversizemsg.input.mode="accept") ++module(load="../plugins/imptcp/.libs/imptcp") ++input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") ++ ++action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ++' ++startup_vg ++echo "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab" > $RSYSLOG_DYNNAME.inputfile ++tcpflood -I $RSYSLOG_DYNNAME.inputfile ++shutdown_when_empty ++wait_shutdown_vg ++check_exit_vg ++ ++# the prime objective is to see if valgrind check is ok, but we also do a quick content check (just in case) ++content_check "received oversize message from peer" ++exit_test +diff --git a/tests/imtcp-octet-framing-too-long-vg.sh b/tests/imtcp-octet-framing-too-long-vg.sh +new file mode 100755 +index 0000000000..88e8a14fb9 +--- /dev/null ++++ b/tests/imtcp-octet-framing-too-long-vg.sh +@@ -0,0 +1,23 @@ ++#!/bin/bash ++# added 2022-04-25 by RGerhards, released under ASL 2.0 ++. ${srcdir:=.}/diag.sh init ++generate_conf ++add_conf ' ++$MaxMessageSize 128 ++global(processInternalMessages="on" ++ oversizemsg.input.mode="accept") ++module(load="../plugins/imtcp/.libs/imtcp") ++input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") ++ ++action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ++' ++startup_vg ++echo "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab" > $RSYSLOG_DYNNAME.inputfile ++tcpflood -I $RSYSLOG_DYNNAME.inputfile ++shutdown_when_empty ++wait_shutdown_vg ++check_exit_vg ++ ++# the prime objective is to see if valgrind check is ok, but we also do a quick content check (just in case) ++content_check "received oversize message from peer" ++exit_test diff --git a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend index de026d919..650c40b41 100644 --- a/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-extended/rsyslog/rsyslog_%.bbappend @@ -1,5 +1,9 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +SRC_URI += " \ + file://CVE-2022-24903.patch \ + " + do_install:append() { sed -i -e"s/ network-online.target//g" ${D}${systemd_system_unitdir}/rsyslog.service -}
\ No newline at end of file +} diff --git a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_1.patch b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_1.patch new file mode 100644 index 000000000..37be3f907 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_1.patch @@ -0,0 +1,42 @@ +From e5905c4b84d4fb90aefcd96ee618411ebfac663d Mon Sep 17 00:00:00 2001 +From: tomspiderlabs <128755403+tomspiderlabs@users.noreply.github.com> +Date: Thu, 23 Mar 2023 23:39:38 +0000 +Subject: [PATCH] Added control character check + +Added control character check, returning -1 (to "err") if control characters are present. +--- + lib/fields.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/lib/fields.c b/lib/fields.c +index 640be931f..fb51b5829 100644 +--- a/lib/fields.c ++++ b/lib/fields.c +@@ -21,9 +21,9 @@ + * + * The supplied field is scanned for non-printable and other illegal + * characters. +- * + -1 is returned if an illegal character is present. +- * + 1 is returned if no illegal characters are present, but the field +- * contains a non-printable character. ++ * + -1 is returned if an illegal or control character is present. ++ * + 1 is returned if no illegal or control characters are present, ++ * but the field contains a non-printable character. + * + 0 is returned otherwise. + */ + int valid_field (const char *field, const char *illegal) +@@ -45,10 +45,13 @@ int valid_field (const char *field, const char *illegal) + } + + if (0 == err) { +- /* Search if there are some non-printable characters */ ++ /* Search if there are non-printable or control characters */ + for (cp = field; '\0' != *cp; cp++) { + if (!isprint (*cp)) { + err = 1; ++ } ++ if (!iscntrl (*cp)) { ++ err = -1; + break; + } + } diff --git a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_2.patch b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_2.patch new file mode 100644 index 000000000..7def7fc7d --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow/CVE-2023-29383_2.patch @@ -0,0 +1,58 @@ +From 2eaea70111f65b16d55998386e4ceb4273c19eb4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com> +Date: Fri, 31 Mar 2023 14:46:50 +0200 +Subject: [PATCH] Overhaul valid_field() + +e5905c4b ("Added control character check") introduced checking for +control characters but had the logic inverted, so it rejects all +characters that are not control ones. + +Cast the character to `unsigned char` before passing to the character +checking functions to avoid UB. + +Use strpbrk(3) for the illegal character test and return early. +--- + lib/fields.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/lib/fields.c b/lib/fields.c +index fb51b5829..539292485 100644 +--- a/lib/fields.c ++++ b/lib/fields.c +@@ -37,26 +37,22 @@ int valid_field (const char *field, const char *illegal) + + /* For each character of field, search if it appears in the list + * of illegal characters. */ ++ if (illegal && NULL != strpbrk (field, illegal)) { ++ return -1; ++ } ++ ++ /* Search if there are non-printable or control characters */ + for (cp = field; '\0' != *cp; cp++) { +- if (strchr (illegal, *cp) != NULL) { ++ unsigned char c = *cp; ++ if (!isprint (c)) { ++ err = 1; ++ } ++ if (iscntrl (c)) { + err = -1; + break; + } + } + +- if (0 == err) { +- /* Search if there are non-printable or control characters */ +- for (cp = field; '\0' != *cp; cp++) { +- if (!isprint (*cp)) { +- err = 1; +- } +- if (!iscntrl (*cp)) { +- err = -1; +- break; +- } +- } +- } +- + return err; + } + diff --git a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend index 31952588b..15fd63096 100644 --- a/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-extended/shadow/shadow_%.bbappend @@ -2,3 +2,7 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" PAM_SRC_URI += "file://pam.d/login \ " +SRC_URI += " \ + file://CVE-2023-29383_1.patch \ + file://CVE-2023-29383_2.patch \ + " diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0004-soc-aspeed-lpc-mbox-Don-t-allow-partial-reads.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0004-soc-aspeed-lpc-mbox-Don-t-allow-partial-reads.patch new file mode 100644 index 000000000..e041e665a --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0004-soc-aspeed-lpc-mbox-Don-t-allow-partial-reads.patch @@ -0,0 +1,40 @@ +From d655ada2fc4b5065c2be6943f28aa4e4f694a1a3 Mon Sep 17 00:00:00 2001 +From: Iwona Winiarska <iwona.winiarska@intel.com> +Date: Mon, 9 Jan 2023 21:09:44 +0100 +Subject: [PATCH] soc: aspeed: lpc-mbox: Don't allow partial reads + +IRQ handler always adds all registers to the fifo, while the userspace +can potentially consume a smaller amount. Unfortunately, when smaller +amount is consumed, it permanently shifts the fifo. +Serialize the "empty" state check to avoid partial reads. + +Fixes: 60fde6cf7114 ("soc: aspeed: lpc-mbox: Avoid calling kfifo_to_user in atomic context") +Reported-by: Arun P. Mohanan <arun.p.m@linux.intel.com> +Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com> +--- + drivers/soc/aspeed/aspeed-lpc-mbox.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/aspeed/aspeed-lpc-mbox.c b/drivers/soc/aspeed/aspeed-lpc-mbox.c +index 7941792abacb..564c7318da10 100644 +--- a/drivers/soc/aspeed/aspeed-lpc-mbox.c ++++ b/drivers/soc/aspeed/aspeed-lpc-mbox.c +@@ -172,7 +172,14 @@ static ssize_t aspeed_mbox_read(struct file *file, char __user *buf, + } + + mutex_lock(&mbox->mutex); +- if (kfifo_is_empty(&mbox->fifo)) { ++ /* ++ * Since fifo on the producer side will drop the oldest values, causing ++ * a shift if the data is not consumed fully, when we're using count == ++ * num_regs reads, we need to serialize with the producer to make ++ * sure that all regs were inserted into fifo (avoiding a partial ++ * read). ++ */ ++ if (kfifo_is_empty_spinlocked(&mbox->fifo, &mbox->lock)) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto out_unlock; +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-ext4-add-EXT4_INODE_HAS_XATTR_SPACE-macro-in-xattr-h.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-ext4-add-EXT4_INODE_HAS_XATTR_SPACE-macro-in-xattr-h.patch new file mode 100644 index 000000000..b4a5465fe --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0005-ext4-add-EXT4_INODE_HAS_XATTR_SPACE-macro-in-xattr-h.patch @@ -0,0 +1,42 @@ +From 179b14152dcb6a24c3415200603aebca70ff13af Mon Sep 17 00:00:00 2001 +From: Baokun Li <libaokun1@huawei.com> +Date: Thu, 16 Jun 2022 10:13:55 +0800 +Subject: [PATCH] ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h + +When adding an xattr to an inode, we must ensure that the inode_size is +not less than EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. Otherwise, +the end position may be greater than the start position, resulting in UAF. + +Signed-off-by: Baokun Li <libaokun1@huawei.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Link: https://lore.kernel.org/r/20220616021358.2504451-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/xattr.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h +index 77efb9a627ad21..f885f362add4af 100644 +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -95,6 +95,19 @@ struct ext4_xattr_entry { + + #define EXT4_ZERO_XATTR_VALUE ((void *)-1) + ++/* ++ * If we want to add an xattr to the inode, we should make sure that ++ * i_extra_isize is not 0 and that the inode size is not less than ++ * EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. ++ * EXT4_GOOD_OLD_INODE_SIZE extra_isize header entry pad data ++ * |--------------------------|------------|------|---------|---|-------| ++ */ ++#define EXT4_INODE_HAS_XATTR_SPACE(inode) \ ++ ((EXT4_I(inode)->i_extra_isize != 0) && \ ++ (EXT4_GOOD_OLD_INODE_SIZE + EXT4_I(inode)->i_extra_isize + \ ++ sizeof(struct ext4_xattr_ibody_header) + EXT4_XATTR_PAD <= \ ++ EXT4_INODE_SIZE((inode)->i_sb))) ++ + struct ext4_xattr_info { + const char *name; + const void *value; diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-36516.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-36516.patch new file mode 100644 index 000000000..dd44c9ce7 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2020-36516.patch @@ -0,0 +1,62 @@ +From 23f57406b82de51809d5812afd96f210f8b627f3 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet <edumazet@google.com> +Date: Wed, 26 Jan 2022 17:10:22 -0800 +Subject: [PATCH] ipv4: avoid using shared IP generator for connected sockets + +ip_select_ident_segs() has been very conservative about using +the connected socket private generator only for packets with IP_DF +set, claiming it was needed for some VJ compression implementations. + +As mentioned in this referenced document, this can be abused. +(Ref: Off-Path TCP Exploits of the Mixed IPID Assignment) + +Before switching to pure random IPID generation and possibly hurt +some workloads, lets use the private inet socket generator. + +Not only this will remove one vulnerability, this will also +improve performance of TCP flows using pmtudisc==IP_PMTUDISC_DONT + +Fixes: 73f156a6e8c1 ("inetpeer: get rid of ip_id_count") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reviewed-by: David Ahern <dsahern@kernel.org> +Reported-by: Ray Che <xijiache@gmail.com> +Cc: Willy Tarreau <w@1wt.eu> +Signed-off-by: Jakub Kicinski <kuba@kernel.org> +--- + include/net/ip.h | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +diff --git a/include/net/ip.h b/include/net/ip.h +index 81e23a102a0d5e..b51bae43b0ddb0 100644 +--- a/include/net/ip.h ++++ b/include/net/ip.h +@@ -525,19 +525,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, + { + struct iphdr *iph = ip_hdr(skb); + ++ /* We had many attacks based on IPID, use the private ++ * generator as much as we can. ++ */ ++ if (sk && inet_sk(sk)->inet_daddr) { ++ iph->id = htons(inet_sk(sk)->inet_id); ++ inet_sk(sk)->inet_id += segs; ++ return; ++ } + if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { +- /* This is only to work around buggy Windows95/2000 +- * VJ compression implementations. If the ID field +- * does not change, they drop every other packet in +- * a TCP stream using header compression. +- */ +- if (sk && inet_sk(sk)->inet_daddr) { +- iph->id = htons(inet_sk(sk)->inet_id); +- inet_sk(sk)->inet_id += segs; +- } else { +- iph->id = 0; +- } ++ iph->id = 0; + } else { ++ /* Unfortunately we need the big hammer to get a suitable IPID */ + __ip_select_ident(net, iph, segs); + } + } diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2978.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2978.patch new file mode 100644 index 000000000..c43941f9f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-2978.patch @@ -0,0 +1,62 @@ +From 2a96b532098284ecf8e4849b8b9e5fc7a28bdee9 Mon Sep 17 00:00:00 2001 +From: Dongliang Mu <mudongliangabcd@gmail.com> +Date: Tue, 16 Aug 2022 12:08:58 +0800 +Subject: [PATCH] fs: fix UAF/GPF bug in nilfs_mdt_destroy +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 2e488f13755ffbb60f307e991b27024716a33b29 upstream. + +In alloc_inode, inode_init_always() could return -ENOMEM if +security_inode_alloc() fails, which causes inode->i_private +uninitialized. Then nilfs_is_metadata_file_inode() returns +true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), +which frees the uninitialized inode->i_private +and leads to crashes(e.g., UAF/GPF). + +Fix this by moving security_inode_alloc just prior to +this_cpu_inc(nr_inodes) + +Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com +Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> +Reported-by: Hao Sun <sunhao.th@gmail.com> +Reported-by: Jiacheng Xu <stitch@zju.edu.cn> +Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org> +Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Cc: stable@vger.kernel.org +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + fs/inode.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/fs/inode.c b/fs/inode.c +index ba1de23c13c1ed..b608528efd3a46 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) + inode->i_wb_frn_history = 0; + #endif + +- if (security_inode_alloc(inode)) +- goto out; + spin_lock_init(&inode->i_lock); + lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); + +@@ -228,11 +226,12 @@ int inode_init_always(struct super_block *sb, struct inode *inode) + inode->i_fsnotify_mask = 0; + #endif + inode->i_flctx = NULL; ++ ++ if (unlikely(security_inode_alloc(inode))) ++ return -ENOMEM; + this_cpu_inc(nr_inodes); + + return 0; +-out: +- return -ENOMEM; + } + EXPORT_SYMBOL(inode_init_always); + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3543.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3543.patch new file mode 100644 index 000000000..9d83b59af --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3543.patch @@ -0,0 +1,97 @@ +From 2f415ad33bc1a729fb1050141921b5a9ec4e062c Mon Sep 17 00:00:00 2001 +From: Kuniyuki Iwashima <kuniyu@amazon.com> +Date: Thu, 29 Sep 2022 08:52:04 -0700 +Subject: [PATCH] af_unix: Fix memory leaks of the whole sk due to OOB skb. + +[ Upstream commit 7a62ed61367b8fd01bae1e18e30602c25060d824 ] + +syzbot reported a sequence of memory leaks, and one of them indicated we +failed to free a whole sk: + + unreferenced object 0xffff8880126e0000 (size 1088): + comm "syz-executor419", pid 326, jiffies 4294773607 (age 12.609s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 7d 00 00 00 00 00 00 00 ........}....... + 01 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace: + [<000000006fefe750>] sk_prot_alloc+0x64/0x2a0 net/core/sock.c:1970 + [<0000000074006db5>] sk_alloc+0x3b/0x800 net/core/sock.c:2029 + [<00000000728cd434>] unix_create1+0xaf/0x920 net/unix/af_unix.c:928 + [<00000000a279a139>] unix_create+0x113/0x1d0 net/unix/af_unix.c:997 + [<0000000068259812>] __sock_create+0x2ab/0x550 net/socket.c:1516 + [<00000000da1521e1>] sock_create net/socket.c:1566 [inline] + [<00000000da1521e1>] __sys_socketpair+0x1a8/0x550 net/socket.c:1698 + [<000000007ab259e1>] __do_sys_socketpair net/socket.c:1751 [inline] + [<000000007ab259e1>] __se_sys_socketpair net/socket.c:1748 [inline] + [<000000007ab259e1>] __x64_sys_socketpair+0x97/0x100 net/socket.c:1748 + [<000000007dedddc1>] do_syscall_x64 arch/x86/entry/common.c:50 [inline] + [<000000007dedddc1>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 + [<000000009456679f>] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +We can reproduce this issue by creating two AF_UNIX SOCK_STREAM sockets, +send()ing an OOB skb to each other, and close()ing them without consuming +the OOB skbs. + + int skpair[2]; + + socketpair(AF_UNIX, SOCK_STREAM, 0, skpair); + + send(skpair[0], "x", 1, MSG_OOB); + send(skpair[1], "x", 1, MSG_OOB); + + close(skpair[0]); + close(skpair[1]); + +Currently, we free an OOB skb in unix_sock_destructor() which is called via +__sk_free(), but it's too late because the receiver's unix_sk(sk)->oob_skb +is accounted against the sender's sk->sk_wmem_alloc and __sk_free() is +called only when sk->sk_wmem_alloc is 0. + +In the repro sequences, we do not consume the OOB skb, so both two sk's +sock_put() never reach __sk_free() due to the positive sk->sk_wmem_alloc. +Then, no one can consume the OOB skb nor call __sk_free(), and we finally +leak the two whole sk. + +Thus, we must free the unconsumed OOB skb earlier when close()ing the +socket. + +Fixes: 314001f0bf92 ("af_unix: Add OOB support") +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Sasha Levin <sashal@kernel.org> +--- + net/unix/af_unix.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index bf338b782fc4c4..d686804119c991 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -569,12 +569,6 @@ static void unix_sock_destructor(struct sock *sk) + + skb_queue_purge(&sk->sk_receive_queue); + +-#if IS_ENABLED(CONFIG_AF_UNIX_OOB) +- if (u->oob_skb) { +- kfree_skb(u->oob_skb); +- u->oob_skb = NULL; +- } +-#endif + WARN_ON(refcount_read(&sk->sk_wmem_alloc)); + WARN_ON(!sk_unhashed(sk)); + WARN_ON(sk->sk_socket); +@@ -620,6 +614,13 @@ static void unix_release_sock(struct sock *sk, int embrion) + + unix_state_unlock(sk); + ++#if IS_ENABLED(CONFIG_AF_UNIX_OOB) ++ if (u->oob_skb) { ++ kfree_skb(u->oob_skb); ++ u->oob_skb = NULL; ++ } ++#endif ++ + wake_up_interruptible_all(&u->peer_wait); + + if (skpair != NULL) { diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3623.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3623.patch new file mode 100644 index 000000000..d44f786de --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-3623.patch @@ -0,0 +1,175 @@ +From fac35ba763ed07ba93154c95ffc0c4a55023707f Mon Sep 17 00:00:00 2001 +From: Baolin Wang <baolin.wang@linux.alibaba.com> +Date: Thu, 1 Sep 2022 18:41:31 +0800 +Subject: mm/hugetlb: fix races when looking up a CONT-PTE/PMD size hugetlb + page + +On some architectures (like ARM64), it can support CONT-PTE/PMD size +hugetlb, which means it can support not only PMD/PUD size hugetlb (2M and +1G), but also CONT-PTE/PMD size(64K and 32M) if a 4K page size specified. + +So when looking up a CONT-PTE size hugetlb page by follow_page(), it will +use pte_offset_map_lock() to get the pte entry lock for the CONT-PTE size +hugetlb in follow_page_pte(). However this pte entry lock is incorrect +for the CONT-PTE size hugetlb, since we should use huge_pte_lock() to get +the correct lock, which is mm->page_table_lock. + +That means the pte entry of the CONT-PTE size hugetlb under current pte +lock is unstable in follow_page_pte(), we can continue to migrate or +poison the pte entry of the CONT-PTE size hugetlb, which can cause some +potential race issues, even though they are under the 'pte lock'. + +For example, suppose thread A is trying to look up a CONT-PTE size hugetlb +page by move_pages() syscall under the lock, however antoher thread B can +migrate the CONT-PTE hugetlb page at the same time, which will cause +thread A to get an incorrect page, if thread A also wants to do page +migration, then data inconsistency error occurs. + +Moreover we have the same issue for CONT-PMD size hugetlb in +follow_huge_pmd(). + +To fix above issues, rename the follow_huge_pmd() as follow_huge_pmd_pte() +to handle PMD and PTE level size hugetlb, which uses huge_pte_lock() to +get the correct pte entry lock to make the pte entry stable. + +Mike said: + +Support for CONT_PMD/_PTE was added with bb9dd3df8ee9 ("arm64: hugetlb: +refactor find_num_contig()"). Patch series "Support for contiguous pte +hugepages", v4. However, I do not believe these code paths were +executed until migration support was added with 5480280d3f2d ("arm64/mm: +enable HugeTLB migration for contiguous bit HugeTLB pages") I would go +with 5480280d3f2d for the Fixes: targe. + +Link: https://lkml.kernel.org/r/635f43bdd85ac2615a58405da82b4d33c6e5eb05.1662017562.git.baolin.wang@linux.alibaba.com +Fixes: 5480280d3f2d ("arm64/mm: enable HugeTLB migration for contiguous bit HugeTLB pages") +Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com> +Suggested-by: Mike Kravetz <mike.kravetz@oracle.com> +Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com> +Cc: David Hildenbrand <david@redhat.com> +Cc: Muchun Song <songmuchun@bytedance.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +--- + include/linux/hugetlb.h | 8 ++++---- + mm/gup.c | 14 +++++++++++++- + mm/hugetlb.c | 27 +++++++++++++-------------- + 3 files changed, 30 insertions(+), 19 deletions(-) + +diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h +index 3ec981a0d8b3a..67c88b82fc32d 100644 +--- a/include/linux/hugetlb.h ++++ b/include/linux/hugetlb.h +@@ -207,8 +207,8 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address, + struct page *follow_huge_pd(struct vm_area_struct *vma, + unsigned long address, hugepd_t hpd, + int flags, int pdshift); +-struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, +- pmd_t *pmd, int flags); ++struct page *follow_huge_pmd_pte(struct vm_area_struct *vma, unsigned long address, ++ int flags); + struct page *follow_huge_pud(struct mm_struct *mm, unsigned long address, + pud_t *pud, int flags); + struct page *follow_huge_pgd(struct mm_struct *mm, unsigned long address, +@@ -312,8 +312,8 @@ static inline struct page *follow_huge_pd(struct vm_area_struct *vma, + return NULL; + } + +-static inline struct page *follow_huge_pmd(struct mm_struct *mm, +- unsigned long address, pmd_t *pmd, int flags) ++static inline struct page *follow_huge_pmd_pte(struct vm_area_struct *vma, ++ unsigned long address, int flags) + { + return NULL; + } +diff --git a/mm/gup.c b/mm/gup.c +index 00926abb44263..251cb6a10bc0d 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -530,6 +530,18 @@ static struct page *follow_page_pte(struct vm_area_struct *vma, + if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) == + (FOLL_PIN | FOLL_GET))) + return ERR_PTR(-EINVAL); ++ ++ /* ++ * Considering PTE level hugetlb, like continuous-PTE hugetlb on ++ * ARM64 architecture. ++ */ ++ if (is_vm_hugetlb_page(vma)) { ++ page = follow_huge_pmd_pte(vma, address, flags); ++ if (page) ++ return page; ++ return no_page_table(vma, flags); ++ } ++ + retry: + if (unlikely(pmd_bad(*pmd))) + return no_page_table(vma, flags); +@@ -662,7 +674,7 @@ static struct page *follow_pmd_mask(struct vm_area_struct *vma, + if (pmd_none(pmdval)) + return no_page_table(vma, flags); + if (pmd_huge(pmdval) && is_vm_hugetlb_page(vma)) { +- page = follow_huge_pmd(mm, address, pmd, flags); ++ page = follow_huge_pmd_pte(vma, address, flags); + if (page) + return page; + return no_page_table(vma, flags); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 0bdfc7e1c933f..9564bf817e6a8 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -6946,12 +6946,13 @@ follow_huge_pd(struct vm_area_struct *vma, + } + + struct page * __weak +-follow_huge_pmd(struct mm_struct *mm, unsigned long address, +- pmd_t *pmd, int flags) ++follow_huge_pmd_pte(struct vm_area_struct *vma, unsigned long address, int flags) + { ++ struct hstate *h = hstate_vma(vma); ++ struct mm_struct *mm = vma->vm_mm; + struct page *page = NULL; + spinlock_t *ptl; +- pte_t pte; ++ pte_t *ptep, pte; + + /* FOLL_GET and FOLL_PIN are mutually exclusive. */ + if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) == +@@ -6961,17 +6962,15 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, + return NULL; + + retry: +- ptl = pmd_lockptr(mm, pmd); +- spin_lock(ptl); +- /* +- * make sure that the address range covered by this pmd is not +- * unmapped from other threads. +- */ +- if (!pmd_huge(*pmd)) +- goto out; +- pte = huge_ptep_get((pte_t *)pmd); ++ ptep = huge_pte_offset(mm, address, huge_page_size(h)); ++ if (!ptep) ++ return NULL; ++ ++ ptl = huge_pte_lock(h, mm, ptep); ++ pte = huge_ptep_get(ptep); + if (pte_present(pte)) { +- page = pmd_page(*pmd) + ((address & ~PMD_MASK) >> PAGE_SHIFT); ++ page = pte_page(pte) + ++ ((address & ~huge_page_mask(h)) >> PAGE_SHIFT); + /* + * try_grab_page() should always succeed here, because: a) we + * hold the pmd (ptl) lock, and b) we've just checked that the +@@ -6987,7 +6986,7 @@ retry: + } else { + if (is_hugetlb_entry_migration(pte)) { + spin_unlock(ptl); +- __migration_entry_wait(mm, (pte_t *)pmd, ptl); ++ __migration_entry_wait_huge(ptep, ptl); + goto retry; + } + /* +-- +cgit + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-42703.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-42703.patch new file mode 100644 index 000000000..059081ce9 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-42703.patch @@ -0,0 +1,169 @@ +From 2555283eb40df89945557273121e9393ef9b542b Mon Sep 17 00:00:00 2001 +From: Jann Horn <jannh@google.com> +Date: Wed, 31 Aug 2022 19:06:00 +0200 +Subject: mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse + +anon_vma->degree tracks the combined number of child anon_vmas and VMAs +that use the anon_vma as their ->anon_vma. + +anon_vma_clone() then assumes that for any anon_vma attached to +src->anon_vma_chain other than src->anon_vma, it is impossible for it to +be a leaf node of the VMA tree, meaning that for such VMAs ->degree is +elevated by 1 because of a child anon_vma, meaning that if ->degree +equals 1 there are no VMAs that use the anon_vma as their ->anon_vma. + +This assumption is wrong because the ->degree optimization leads to leaf +nodes being abandoned on anon_vma_clone() - an existing anon_vma is +reused and no new parent-child relationship is created. So it is +possible to reuse an anon_vma for one VMA while it is still tied to +another VMA. + +This is an issue because is_mergeable_anon_vma() and its callers assume +that if two VMAs have the same ->anon_vma, the list of anon_vmas +attached to the VMAs is guaranteed to be the same. When this assumption +is violated, vma_merge() can merge pages into a VMA that is not attached +to the corresponding anon_vma, leading to dangling page->mapping +pointers that will be dereferenced during rmap walks. + +Fix it by separately tracking the number of child anon_vmas and the +number of VMAs using the anon_vma as their ->anon_vma. + +Fixes: 7a3ef208e662 ("mm: prevent endless growth of anon_vma hierarchy") +Cc: stable@kernel.org +Acked-by: Michal Hocko <mhocko@suse.com> +Acked-by: Vlastimil Babka <vbabka@suse.cz> +Signed-off-by: Jann Horn <jannh@google.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + include/linux/rmap.h | 7 +++++-- + mm/rmap.c | 29 ++++++++++++++++------------- + 2 files changed, 21 insertions(+), 15 deletions(-) + +diff --git a/include/linux/rmap.h b/include/linux/rmap.h +index bf80adca980b9..b89b4b86951f8 100644 +--- a/include/linux/rmap.h ++++ b/include/linux/rmap.h +@@ -41,12 +41,15 @@ struct anon_vma { + atomic_t refcount; + + /* +- * Count of child anon_vmas and VMAs which points to this anon_vma. ++ * Count of child anon_vmas. Equals to the count of all anon_vmas that ++ * have ->parent pointing to this one, including itself. + * + * This counter is used for making decision about reusing anon_vma + * instead of forking new one. See comments in function anon_vma_clone. + */ +- unsigned degree; ++ unsigned long num_children; ++ /* Count of VMAs whose ->anon_vma pointer points to this object. */ ++ unsigned long num_active_vmas; + + struct anon_vma *parent; /* Parent of this anon_vma */ + +diff --git a/mm/rmap.c b/mm/rmap.c +index edc06c52bc82e..93d5a6f793d20 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -93,7 +93,8 @@ static inline struct anon_vma *anon_vma_alloc(void) + anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL); + if (anon_vma) { + atomic_set(&anon_vma->refcount, 1); +- anon_vma->degree = 1; /* Reference for first vma */ ++ anon_vma->num_children = 0; ++ anon_vma->num_active_vmas = 0; + anon_vma->parent = anon_vma; + /* + * Initialise the anon_vma root to point to itself. If called +@@ -201,6 +202,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma) + anon_vma = anon_vma_alloc(); + if (unlikely(!anon_vma)) + goto out_enomem_free_avc; ++ anon_vma->num_children++; /* self-parent link for new root */ + allocated = anon_vma; + } + +@@ -210,8 +212,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma) + if (likely(!vma->anon_vma)) { + vma->anon_vma = anon_vma; + anon_vma_chain_link(vma, avc, anon_vma); +- /* vma reference or self-parent link for new root */ +- anon_vma->degree++; ++ anon_vma->num_active_vmas++; + allocated = NULL; + avc = NULL; + } +@@ -296,19 +297,19 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src) + anon_vma_chain_link(dst, avc, anon_vma); + + /* +- * Reuse existing anon_vma if its degree lower than two, +- * that means it has no vma and only one anon_vma child. ++ * Reuse existing anon_vma if it has no vma and only one ++ * anon_vma child. + * +- * Do not chose parent anon_vma, otherwise first child +- * will always reuse it. Root anon_vma is never reused: ++ * Root anon_vma is never reused: + * it has self-parent reference and at least one child. + */ + if (!dst->anon_vma && src->anon_vma && +- anon_vma != src->anon_vma && anon_vma->degree < 2) ++ anon_vma->num_children < 2 && ++ anon_vma->num_active_vmas == 0) + dst->anon_vma = anon_vma; + } + if (dst->anon_vma) +- dst->anon_vma->degree++; ++ dst->anon_vma->num_active_vmas++; + unlock_anon_vma_root(root); + return 0; + +@@ -358,6 +359,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + anon_vma = anon_vma_alloc(); + if (!anon_vma) + goto out_error; ++ anon_vma->num_active_vmas++; + avc = anon_vma_chain_alloc(GFP_KERNEL); + if (!avc) + goto out_error_free_anon_vma; +@@ -378,7 +380,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma) + vma->anon_vma = anon_vma; + anon_vma_lock_write(anon_vma); + anon_vma_chain_link(vma, avc, anon_vma); +- anon_vma->parent->degree++; ++ anon_vma->parent->num_children++; + anon_vma_unlock_write(anon_vma); + + return 0; +@@ -410,7 +412,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma) + * to free them outside the lock. + */ + if (RB_EMPTY_ROOT(&anon_vma->rb_root.rb_root)) { +- anon_vma->parent->degree--; ++ anon_vma->parent->num_children--; + continue; + } + +@@ -418,7 +420,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma) + anon_vma_chain_free(avc); + } + if (vma->anon_vma) { +- vma->anon_vma->degree--; ++ vma->anon_vma->num_active_vmas--; + + /* + * vma would still be needed after unlink, and anon_vma will be prepared +@@ -436,7 +438,8 @@ void unlink_anon_vmas(struct vm_area_struct *vma) + list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) { + struct anon_vma *anon_vma = avc->anon_vma; + +- VM_WARN_ON(anon_vma->degree); ++ VM_WARN_ON(anon_vma->num_children); ++ VM_WARN_ON(anon_vma->num_active_vmas); + put_anon_vma(anon_vma); + + list_del(&avc->same_vma); +-- +cgit + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-1.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-1.patch new file mode 100644 index 000000000..15fea2b32 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-1.patch @@ -0,0 +1,107 @@ +From fdf2c95f28bf197bfab421d21e8c697d4f149ea1 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Mon, 5 Dec 2022 12:09:06 -0800 +Subject: [PATCH] proc: proc_skip_spaces() shouldn't think it is working on C + strings + +commit bce9332220bd677d83b19d21502776ad555a0e73 upstream. + +proc_skip_spaces() seems to think it is working on C strings, and ends +up being just a wrapper around skip_spaces() with a really odd calling +convention. + +Instead of basing it on skip_spaces(), it should have looked more like +proc_skip_char(), which really is the exact same function (except it +skips a particular character, rather than whitespace). So use that as +inspiration, odd coding and all. + +Now the calling convention actually makes sense and works for the +intended purpose. + +Reported-and-tested-by: Kyle Zeng <zengyhkyle@gmail.com> +Acked-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/sysctl.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 25b44424d652cf..e9a3094c52e57a 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -265,13 +265,14 @@ int proc_dostring(struct ctl_table *table, int write, + ppos); + } + +-static size_t proc_skip_spaces(char **buf) ++static void proc_skip_spaces(char **buf, size_t *size) + { +- size_t ret; +- char *tmp = skip_spaces(*buf); +- ret = tmp - *buf; +- *buf = tmp; +- return ret; ++ while (*size) { ++ if (!isspace(**buf)) ++ break; ++ (*size)--; ++ (*buf)++; ++ } + } + + static void proc_skip_char(char **buf, size_t *size, const char v) +@@ -518,7 +519,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, + bool neg; + + if (write) { +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + + if (!left) + break; +@@ -545,7 +546,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, + if (!write && !first && left && !err) + proc_put_char(&buffer, &left, '\n'); + if (write && !err && left) +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + if (write && first) + return err ? : -EINVAL; + *lenp -= left; +@@ -587,7 +588,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data, + if (left > PAGE_SIZE - 1) + left = PAGE_SIZE - 1; + +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + if (!left) { + err = -EINVAL; + goto out_free; +@@ -607,7 +608,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data, + } + + if (!err && left) +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + + out_free: + if (err) +@@ -1072,7 +1073,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, + if (write) { + bool neg; + +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + if (!left) + break; + +@@ -1101,7 +1102,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, + if (!write && !first && left && !err) + proc_put_char(&buffer, &left, '\n'); + if (write && !err) +- left -= proc_skip_spaces(&p); ++ proc_skip_spaces(&p, &left); + if (write && first) + return err ? : -EINVAL; + *lenp -= left; diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-2.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-2.patch new file mode 100644 index 000000000..b11e065c8 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2022-4378-2.patch @@ -0,0 +1,40 @@ +From e04220518841708f68e7746232e3e54daef464a3 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Mon, 5 Dec 2022 11:33:40 -0800 +Subject: [PATCH] proc: avoid integer type confusion in get_proc_long + +commit e6cfaf34be9fcd1a8285a294e18986bfc41a409c upstream. + +proc_get_long() is passed a size_t, but then assigns it to an 'int' +variable for the length. Let's not do that, even if our IO paths are +limited to MAX_RW_COUNT (exactly because of these kinds of type errors). + +So do the proper test in the rigth type. + +Reported-by: Kyle Zeng <zengyhkyle@gmail.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + kernel/sysctl.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 205d605cacc5bb..25b44424d652cf 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -340,13 +340,12 @@ static int proc_get_long(char **buf, size_t *size, + unsigned long *val, bool *neg, + const char *perm_tr, unsigned perm_tr_len, char *tr) + { +- int len; + char *p, tmp[TMPBUFLEN]; ++ ssize_t len = *size; + +- if (!*size) ++ if (len <= 0) + return -EINVAL; + +- len = *size; + if (len > TMPBUFLEN - 1) + len = TMPBUFLEN - 1; + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-0394.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-0394.patch new file mode 100644 index 000000000..25ffd9af5 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-0394.patch @@ -0,0 +1,43 @@ +From cb3e9864cdbe35ff6378966660edbcbac955fe17 Mon Sep 17 00:00:00 2001 +From: Herbert Xu <herbert@gondor.apana.org.au> +Date: Tue, 10 Jan 2023 08:59:06 +0800 +Subject: ipv6: raw: Deduct extension header length in + rawv6_push_pending_frames + +The total cork length created by ip6_append_data includes extension +headers, so we must exclude them when comparing them against the +IPV6_CHECKSUM offset which does not include extension headers. + +Reported-by: Kyle Zeng <zengyhkyle@gmail.com> +Fixes: 357b40a18b04 ("[IPV6]: IPV6_CHECKSUM socket option can corrupt kernel memory") +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/ipv6/raw.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index a06a9f847db5c..ada087b50541a 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -505,6 +505,7 @@ csum_copy_err: + static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct raw6_sock *rp) + { ++ struct ipv6_txoptions *opt; + struct sk_buff *skb; + int err = 0; + int offset; +@@ -522,6 +523,9 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + + offset = rp->offset; + total_len = inet_sk(sk)->cork.base.length; ++ opt = inet6_sk(sk)->cork.opt; ++ total_len -= opt ? opt->opt_flen : 0; ++ + if (offset >= total_len - 1) { + err = -EINVAL; + ip6_flush_pending_frames(sk); +-- +cgit + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1073.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1073.patch new file mode 100644 index 000000000..fbad7dd75 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1073.patch @@ -0,0 +1,34 @@ +From b12fece4c64857e5fab4290bf01b2e0317a88456 Mon Sep 17 00:00:00 2001 +From: Pietro Borrello <borrello@diag.uniroma1.it> +Date: Mon, 16 Jan 2023 11:11:24 +0000 +Subject: [PATCH] HID: check empty report_list in hid_validate_values() + +Add a check for empty report_list in hid_validate_values(). +The missing check causes a type confusion when issuing a list_entry() +on an empty report_list. +The problem is caused by the assumption that the device must +have valid report_list. While this will be true for all normal HID +devices, a suitably malicious device can violate the assumption. + +Fixes: 1b15d2e5b807 ("HID: core: fix validation of report id 0") +Signed-off-by: Pietro Borrello <borrello@diag.uniroma1.it> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +--- + drivers/hid/hid-core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index bd47628da6be0d..3e1803592bd4a2 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -993,8 +993,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid, + * Validating on id 0 means we should examine the first + * report in the list. + */ +- report = list_entry( +- hid->report_enum[type].report_list.next, ++ report = list_first_entry_or_null( ++ &hid->report_enum[type].report_list, + struct hid_report, list); + } else { + report = hid->report_enum[type].report_id_hash[id]; diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1077.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1077.patch new file mode 100644 index 000000000..7bf9fad09 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1077.patch @@ -0,0 +1,50 @@ +From 71d8dc030a8ebf8401d96872d0ed2d151a4cdbba Mon Sep 17 00:00:00 2001 +From: Anjaliintel-21 <anjali.ray@intel.com> +Date: Thu, 27 Apr 2023 07:01:53 +0000 +Subject: [PATCH] sched/rt: pick_next_rt_entity(): check list_entry + +Commit 326587b84078 ("sched: fix goto retry in pick_next_task_rt()") +removed any path which could make pick_next_rt_entity() return NULL. +However, BUG_ON(!rt_se) in _pick_next_task_rt() (the only caller of +pick_next_rt_entity()) still checks the error condition, which can +never happen, since list_entry() never returns NULL. +Remove the BUG_ON check, and instead emit a warning in the only +possible error condition here: the queue being empty which should +never happen. + +Fixes: 326587b84078 ("sched: fix goto retry in pick_next_task_rt()") +Signed-off-by: Pietro Borrello <borrello@diag.uniroma1.it> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Reviewed-by: Phil Auld <pauld@redhat.com> +Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org> +Link: https://lore.kernel.org/r/20230128-list-entry-null-check-sched-v3-1-b1a71bd1ac6b@diag.uniroma1.it +--- + kernel/sched/rt.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index 3daf42a0f462..c70c328bd89a 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -1607,6 +1607,8 @@ static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq, + BUG_ON(idx >= MAX_RT_PRIO); + + queue = array->queue + idx; ++ if (SCHED_WARN_ON(list_empty(queue))) ++ return NULL; + next = list_entry(queue->next, struct sched_rt_entity, run_list); + + return next; +@@ -1619,7 +1621,8 @@ static struct task_struct *_pick_next_task_rt(struct rq *rq) + + do { + rt_se = pick_next_rt_entity(rq, rt_rq); +- BUG_ON(!rt_se); ++ if (unlikely(!rt_se)) ++ return NULL; + rt_rq = group_rt_rq(rt_se); + } while (rt_rq); + +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch new file mode 100644 index 000000000..89a7f7949 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1252.patch @@ -0,0 +1,89 @@ +From 9a254403760041528bc8f69fe2f5e1ef86950991 Mon Sep 17 00:00:00 2001 +From: yangerkun <yangerkun@huawei.com> +Date: Thu, 30 Sep 2021 11:22:28 +0800 +Subject: [PATCH] ovl: fix use after free in struct ovl_aio_req + +Example for triggering use after free in a overlay on ext4 setup: + +aio_read + ovl_read_iter + vfs_iter_read + ext4_file_read_iter + ext4_dio_read_iter + iomap_dio_rw -> -EIOCBQUEUED + /* + * Here IO is completed in a separate thread, + * ovl_aio_cleanup_handler() frees aio_req which has iocb embedded + */ + file_accessed(iocb->ki_filp); /**BOOM**/ + +Fix by introducing a refcount in ovl_aio_req similarly to aio_kiocb. This +guarantees that iocb is only freed after vfs_read/write_iter() returns on +underlying fs. + +Fixes: 2406a307ac7d ("ovl: implement async IO routines") +Signed-off-by: yangerkun <yangerkun@huawei.com> +Link: https://lore.kernel.org/r/20210930032228.3199690-3-yangerkun@huawei.com/ +Cc: <stable@vger.kernel.org> # v5.6 +Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> +--- + fs/overlayfs/file.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index c88ac571593dc1..44fea16751f1db 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -17,6 +17,7 @@ + + struct ovl_aio_req { + struct kiocb iocb; ++ refcount_t ref; + struct kiocb *orig_iocb; + struct fd fd; + }; +@@ -252,6 +253,14 @@ static rwf_t ovl_iocb_to_rwf(int ifl) + return flags; + } + ++static inline void ovl_aio_put(struct ovl_aio_req *aio_req) ++{ ++ if (refcount_dec_and_test(&aio_req->ref)) { ++ fdput(aio_req->fd); ++ kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ } ++} ++ + static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + { + struct kiocb *iocb = &aio_req->iocb; +@@ -268,8 +277,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + } + + orig_iocb->ki_pos = iocb->ki_pos; +- fdput(aio_req->fd); +- kmem_cache_free(ovl_aio_request_cachep, aio_req); ++ ovl_aio_put(aio_req); + } + + static void ovl_aio_rw_complete(struct kiocb *iocb, long res, long res2) +@@ -319,7 +327,9 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) + aio_req->orig_iocb = iocb; + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_read(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } +@@ -390,7 +400,9 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) + kiocb_clone(&aio_req->iocb, iocb, real.file); + aio_req->iocb.ki_flags = ifl; + aio_req->iocb.ki_complete = ovl_aio_rw_complete; ++ refcount_set(&aio_req->ref, 2); + ret = vfs_iocb_iter_write(real.file, &aio_req->iocb, iter); ++ ovl_aio_put(aio_req); + if (ret != -EIOCBQUEUED) + ovl_aio_cleanup_handler(aio_req); + } diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1582.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1582.patch new file mode 100644 index 000000000..c38b93c78 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-1582.patch @@ -0,0 +1,228 @@ +From 24d7275ce2791829953ed4e72f68277ceb2571c6 Mon Sep 17 00:00:00 2001 +From: Yang Shi <shy828301@gmail.com> +Date: Fri, 11 Feb 2022 16:32:26 -0800 +Subject: [PATCH] fs/proc: task_mmu.c: don't read mapcount for migration entry + +The syzbot reported the below BUG: + + kernel BUG at include/linux/page-flags.h:785! + invalid opcode: 0000 [#1] PREEMPT SMP KASAN + CPU: 1 PID: 4392 Comm: syz-executor560 Not tainted 5.16.0-rc6-syzkaller #0 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 + RIP: 0010:PageDoubleMap include/linux/page-flags.h:785 [inline] + RIP: 0010:__page_mapcount+0x2d2/0x350 mm/util.c:744 + Call Trace: + page_mapcount include/linux/mm.h:837 [inline] + smaps_account+0x470/0xb10 fs/proc/task_mmu.c:466 + smaps_pte_entry fs/proc/task_mmu.c:538 [inline] + smaps_pte_range+0x611/0x1250 fs/proc/task_mmu.c:601 + walk_pmd_range mm/pagewalk.c:128 [inline] + walk_pud_range mm/pagewalk.c:205 [inline] + walk_p4d_range mm/pagewalk.c:240 [inline] + walk_pgd_range mm/pagewalk.c:277 [inline] + __walk_page_range+0xe23/0x1ea0 mm/pagewalk.c:379 + walk_page_vma+0x277/0x350 mm/pagewalk.c:530 + smap_gather_stats.part.0+0x148/0x260 fs/proc/task_mmu.c:768 + smap_gather_stats fs/proc/task_mmu.c:741 [inline] + show_smap+0xc6/0x440 fs/proc/task_mmu.c:822 + seq_read_iter+0xbb0/0x1240 fs/seq_file.c:272 + seq_read+0x3e0/0x5b0 fs/seq_file.c:162 + vfs_read+0x1b5/0x600 fs/read_write.c:479 + ksys_read+0x12d/0x250 fs/read_write.c:619 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +The reproducer was trying to read /proc/$PID/smaps when calling +MADV_FREE at the mean time. MADV_FREE may split THPs if it is called +for partial THP. It may trigger the below race: + + CPU A CPU B + ----- ----- + smaps walk: MADV_FREE: + page_mapcount() + PageCompound() + split_huge_page() + page = compound_head(page) + PageDoubleMap(page) + +When calling PageDoubleMap() this page is not a tail page of THP anymore +so the BUG is triggered. + +This could be fixed by elevated refcount of the page before calling +mapcount, but that would prevent it from counting migration entries, and +it seems overkilling because the race just could happen when PMD is +split so all PTE entries of tail pages are actually migration entries, +and smaps_account() does treat migration entries as mapcount == 1 as +Kirill pointed out. + +Add a new parameter for smaps_account() to tell this entry is migration +entry then skip calling page_mapcount(). Don't skip getting mapcount +for device private entries since they do track references with mapcount. + +Pagemap also has the similar issue although it was not reported. Fixed +it as well. + +[shy828301@gmail.com: v4] + Link: https://lkml.kernel.org/r/20220203182641.824731-1-shy828301@gmail.com +[nathan@kernel.org: avoid unused variable warning in pagemap_pmd_range()] + Link: https://lkml.kernel.org/r/20220207171049.1102239-1-nathan@kernel.org +Link: https://lkml.kernel.org/r/20220120202805.3369-1-shy828301@gmail.com +Fixes: e9b61f19858a ("thp: reintroduce split_huge_page()") +Signed-off-by: Yang Shi <shy828301@gmail.com> +Signed-off-by: Nathan Chancellor <nathan@kernel.org> +Reported-by: syzbot+1f52b3a18d5633fa7f82@syzkaller.appspotmail.com +Acked-by: David Hildenbrand <david@redhat.com> +Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Jann Horn <jannh@google.com> +Cc: Matthew Wilcox <willy@infradead.org> +Cc: Alexey Dobriyan <adobriyan@gmail.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +--- + fs/proc/task_mmu.c | 40 +++++++++++++++++++++++++++++++--------- + 1 file changed, 31 insertions(+), 9 deletions(-) + +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index cf25be3e0321..3e68cc9e816c 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -430,7 +430,8 @@ static void smaps_page_accumulate(struct mem_size_stats *mss, + } + + static void smaps_account(struct mem_size_stats *mss, struct page *page, +- bool compound, bool young, bool dirty, bool locked) ++ bool compound, bool young, bool dirty, bool locked, ++ bool migration) + { + int i, nr = compound ? compound_nr(page) : 1; + unsigned long size = nr * PAGE_SIZE; +@@ -457,8 +458,15 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page, + * page_count(page) == 1 guarantees the page is mapped exactly once. + * If any subpage of the compound page mapped with PTE it would elevate + * page_count(). ++ * ++ * The page_mapcount() is called to get a snapshot of the mapcount. ++ * Without holding the page lock this snapshot can be slightly wrong as ++ * we cannot always read the mapcount atomically. It is not safe to ++ * call page_mapcount() even with PTL held if the page is not mapped, ++ * especially for migration entries. Treat regular migration entries ++ * as mapcount == 1. + */ +- if (page_count(page) == 1) { ++ if ((page_count(page) == 1) || migration) { + smaps_page_accumulate(mss, page, size, size << PSS_SHIFT, dirty, + locked, true); + return; +@@ -495,6 +503,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + struct vm_area_struct *vma = walk->vma; + bool locked = !!(vma->vm_flags & VM_LOCKED); + struct page *page = NULL; ++ bool migration = false; + + if (pte_present(*pte)) { + page = vm_normal_page(vma, addr, *pte); +@@ -514,8 +523,11 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + } else { + mss->swap_pss += (u64)PAGE_SIZE << PSS_SHIFT; + } +- } else if (is_pfn_swap_entry(swpent)) ++ } else if (is_pfn_swap_entry(swpent)){ ++ if (is_migration_entry(swpent)) ++ migration = true; + page = pfn_swap_entry_to_page(swpent); ++ } + } else if (unlikely(IS_ENABLED(CONFIG_SHMEM) && mss->check_shmem_swap + && pte_none(*pte))) { + page = xa_load(&vma->vm_file->f_mapping->i_pages, +@@ -528,7 +540,8 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr, + if (!page) + return; + +- smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked); ++ smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), ++ locked, migration); + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE +@@ -539,6 +552,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + struct vm_area_struct *vma = walk->vma; + bool locked = !!(vma->vm_flags & VM_LOCKED); + struct page *page = NULL; ++ bool migration = false; + + if (pmd_present(*pmd)) { + /* FOLL_DUMP will return -EFAULT on huge zero page */ +@@ -546,8 +560,10 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + } else if (unlikely(thp_migration_supported() && is_swap_pmd(*pmd))) { + swp_entry_t entry = pmd_to_swp_entry(*pmd); + +- if (is_migration_entry(entry)) ++ if (is_migration_entry(entry)) { ++ migration = true; + page = pfn_swap_entry_to_page(entry); ++ } + } + if (IS_ERR_OR_NULL(page)) + return; +@@ -559,7 +575,9 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, + /* pass */; + else + mss->file_thp += HPAGE_PMD_SIZE; +- smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked); ++ ++ smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), ++ locked, migration); + } + #else + static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr, +@@ -1363,6 +1381,7 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm, + { + u64 frame = 0, flags = 0; + struct page *page = NULL; ++ bool migration = false; + + if (pte_present(pte)) { + if (pm->show_pfn) +@@ -1384,13 +1403,14 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm, + frame = swp_type(entry) | + (swp_offset(entry) << MAX_SWAPFILES_SHIFT); + flags |= PM_SWAP; ++ migration = is_migration_entry(entry); + if (is_pfn_swap_entry(entry)) + page = pfn_swap_entry_to_page(entry); + } + + if (page && !PageAnon(page)) + flags |= PM_FILE; +- if (page && page_mapcount(page) == 1) ++ if (page && !migration && page_mapcount(page) == 1) + flags |= PM_MMAP_EXCLUSIVE; + if (vma->vm_flags & VM_SOFTDIRTY) + flags |= PM_SOFT_DIRTY; +@@ -1406,8 +1426,9 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, + spinlock_t *ptl; + pte_t *pte, *orig_pte; + int err = 0; +- + #ifdef CONFIG_TRANSPARENT_HUGEPAGE ++ bool migration = false; ++ + ptl = pmd_trans_huge_lock(pmdp, vma); + if (ptl) { + u64 flags = 0, frame = 0; +@@ -1446,11 +1467,12 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end, + if (pmd_swp_uffd_wp(pmd)) + flags |= PM_UFFD_WP; + VM_BUG_ON(!is_pmd_migration_entry(pmd)); ++ migration = is_migration_entry(entry); + page = pfn_swap_entry_to_page(entry); + } + #endif + +- if (page && page_mapcount(page) == 1) ++ if (page && !migration && page_mapcount(page) == 1) + flags |= PM_MMAP_EXCLUSIVE; + + for (; addr != end; addr += PAGE_SIZE) { diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2269.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2269.patch new file mode 100644 index 000000000..538318fe0 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2269.patch @@ -0,0 +1,56 @@ +From 3d32aaa7e66d5c1479a3c31d6c2c5d45dd0d3b89 Mon Sep 17 00:00:00 2001 +From: Mike Snitzer <snitzer@kernel.org> +Date: Mon, 17 Apr 2023 11:59:56 -0400 +Subject: [PATCH] dm ioctl: fix nested locking in table_clear() to remove + deadlock concern + +syzkaller found the following problematic rwsem locking (with write +lock already held): + + down_read+0x9d/0x450 kernel/locking/rwsem.c:1509 + dm_get_inactive_table+0x2b/0xc0 drivers/md/dm-ioctl.c:773 + __dev_status+0x4fd/0x7c0 drivers/md/dm-ioctl.c:844 + table_clear+0x197/0x280 drivers/md/dm-ioctl.c:1537 + +In table_clear, it first acquires a write lock +https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L1520 +down_write(&_hash_lock); + +Then before the lock is released at L1539, there is a path shown above: +table_clear -> __dev_status -> dm_get_inactive_table -> down_read +https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L773 +down_read(&_hash_lock); + +It tries to acquire the same read lock again, resulting in the deadlock +problem. + +Fix this by moving table_clear()'s __dev_status() call to after its +up_write(&_hash_lock); + +Cc: stable@vger.kernel.org +Reported-by: Zheng Zhang <zheng.zhang@email.ucr.edu> +Signed-off-by: Mike Snitzer <snitzer@kernel.org> +--- + drivers/md/dm-ioctl.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c +index 50a1259294d141..7d5c9c582ed2d6 100644 +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1556,11 +1556,12 @@ static int table_clear(struct file *filp, struct dm_ioctl *param, size_t param_s + has_new_map = true; + } + +- param->flags &= ~DM_INACTIVE_PRESENT_FLAG; +- +- __dev_status(hc->md, param); + md = hc->md; + up_write(&_hash_lock); ++ ++ param->flags &= ~DM_INACTIVE_PRESENT_FLAG; ++ __dev_status(md, param); ++ + if (old_map) { + dm_sync_table(md); + dm_table_destroy(old_map); diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2513.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2513.patch new file mode 100644 index 000000000..266fedb1f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2023-2513.patch @@ -0,0 +1,120 @@ +From 67d7d8ad99beccd9fe92d585b87f1760dc9018e3 Mon Sep 17 00:00:00 2001 +From: Baokun Li <libaokun1@huawei.com> +Date: Thu, 16 Jun 2022 10:13:56 +0800 +Subject: [PATCH] ext4: fix use-after-free in ext4_xattr_set_entry + +Hulk Robot reported a issue: +================================================================== +BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x18ab/0x3500 +Write of size 4105 at addr ffff8881675ef5f4 by task syz-executor.0/7092 + +CPU: 1 PID: 7092 Comm: syz-executor.0 Not tainted 4.19.90-dirty #17 +Call Trace: +[...] + memcpy+0x34/0x50 mm/kasan/kasan.c:303 + ext4_xattr_set_entry+0x18ab/0x3500 fs/ext4/xattr.c:1747 + ext4_xattr_ibody_inline_set+0x86/0x2a0 fs/ext4/xattr.c:2205 + ext4_xattr_set_handle+0x940/0x1300 fs/ext4/xattr.c:2386 + ext4_xattr_set+0x1da/0x300 fs/ext4/xattr.c:2498 + __vfs_setxattr+0x112/0x170 fs/xattr.c:149 + __vfs_setxattr_noperm+0x11b/0x2a0 fs/xattr.c:180 + __vfs_setxattr_locked+0x17b/0x250 fs/xattr.c:238 + vfs_setxattr+0xed/0x270 fs/xattr.c:255 + setxattr+0x235/0x330 fs/xattr.c:520 + path_setxattr+0x176/0x190 fs/xattr.c:539 + __do_sys_lsetxattr fs/xattr.c:561 [inline] + __se_sys_lsetxattr fs/xattr.c:557 [inline] + __x64_sys_lsetxattr+0xc2/0x160 fs/xattr.c:557 + do_syscall_64+0xdf/0x530 arch/x86/entry/common.c:298 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +RIP: 0033:0x459fe9 +RSP: 002b:00007fa5e54b4c08 EFLAGS: 00000246 ORIG_RAX: 00000000000000bd +RAX: ffffffffffffffda RBX: 000000000051bf60 RCX: 0000000000459fe9 +RDX: 00000000200003c0 RSI: 0000000020000180 RDI: 0000000020000140 +RBP: 000000000051bf60 R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000001009 R11: 0000000000000246 R12: 0000000000000000 +R13: 00007ffc73c93fc0 R14: 000000000051bf60 R15: 00007fa5e54b4d80 +[...] +================================================================== + +Above issue may happen as follows: +------------------------------------- +ext4_xattr_set + ext4_xattr_set_handle + ext4_xattr_ibody_find + >> s->end < s->base + >> no EXT4_STATE_XATTR + >> xattr_check_inode is not executed + ext4_xattr_ibody_set + ext4_xattr_set_entry + >> size_t min_offs = s->end - s->base + >> UAF in memcpy + +we can easily reproduce this problem with the following commands: + mkfs.ext4 -F /dev/sda + mount -o debug_want_extra_isize=128 /dev/sda /mnt + touch /mnt/file + setfattr -n user.cat -v `seq -s z 4096|tr -d '[:digit:]'` /mnt/file + +In ext4_xattr_ibody_find, we have the following assignment logic: + header = IHDR(inode, raw_inode) + = raw_inode + EXT4_GOOD_OLD_INODE_SIZE + i_extra_isize + is->s.base = IFIRST(header) + = header + sizeof(struct ext4_xattr_ibody_header) + is->s.end = raw_inode + s_inode_size + +In ext4_xattr_set_entry + min_offs = s->end - s->base + = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize - + sizeof(struct ext4_xattr_ibody_header) + last = s->first + free = min_offs - ((void *)last - s->base) - sizeof(__u32) + = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize - + sizeof(struct ext4_xattr_ibody_header) - sizeof(__u32) + +In the calculation formula, all values except s_inode_size and +i_extra_size are fixed values. When i_extra_size is the maximum value +s_inode_size - EXT4_GOOD_OLD_INODE_SIZE, min_offs is -4 and free is -8. +The value overflows. As a result, the preceding issue is triggered when +memcpy is executed. + +Therefore, when finding xattr or setting xattr, check whether +there is space for storing xattr in the inode to resolve this issue. + +Cc: stable@kernel.org +Reported-by: Hulk Robot <hulkci@huawei.com> +Signed-off-by: Baokun Li <libaokun1@huawei.com> +Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Link: https://lore.kernel.org/r/20220616021358.2504451-3-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +--- + fs/ext4/xattr.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 564e28a1aa9428..c42b3e0d2d94b4 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2175,8 +2175,9 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + struct ext4_inode *raw_inode; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return 0; ++ + raw_inode = ext4_raw_inode(&is->iloc); + header = IHDR(inode, raw_inode); + is->s.base = is->s.first = IFIRST(header); +@@ -2204,8 +2205,9 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + struct ext4_xattr_search *s = &is->s; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return -ENOSPC; ++ + error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); + if (error) + return error; diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend index 92620086d..b3b22b408 100644 --- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend @@ -52,7 +52,22 @@ SRC_URI += " \ file://CVE-2022-2663-1.patch\ file://CVE-2022-2663-2.patch\ file://CVE-2022-20158-1.patch\ + file://0004-soc-aspeed-lpc-mbox-Don-t-allow-partial-reads.patch \ + file://CVE-2022-3543.patch \ + file://CVE-2022-42703.patch \ + file://CVE-2022-4378-1.patch \ + file://CVE-2022-4378-2.patch \ + file://CVE-2022-2978.patch \ + file://CVE-2022-3623.patch \ + file://CVE-2023-0394.patch \ + file://CVE-2023-1252.patch\ + file://CVE-2023-1073.patch\ + file://CVE-2023-1077.patch\ + file://CVE-2023-1582.patch \ + file://CVE-2020-36516.patch \ + file://0005-ext4-add-EXT4_INODE_HAS_XATTR_SPACE-macro-in-xattr-h.patch \ + file://CVE-2023-2513.patch \ + file://CVE-2023-2269.patch \ " - SRC_URI += "${@bb.utils.contains('IMAGE_FSTYPES', 'intel-pfr', 'file://1000-128MB-flashmap-for-PFR.patch', '', d)}" SRC_URI += "${@bb.utils.contains('EXTRA_IMAGE_FEATURES', 'debug-tweaks', 'file://debug.cfg', '', d)}" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0008-dynamic-threshold-configuration-for-SOLUM-PSU.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0008-dynamic-threshold-configuration-for-SOLUM-PSU.patch new file mode 100644 index 000000000..16df1b436 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0008-dynamic-threshold-configuration-for-SOLUM-PSU.patch @@ -0,0 +1,90 @@ +From d7425aa548716339e9c00a45695f93c294613cd4 Mon Sep 17 00:00:00 2001 +From: Vikash Chandola <vikash.chandola@intel.com> +Date: Fri, 5 Aug 2022 12:57:51 +0000 +Subject: [PATCH] dynamic threshold configuration for SOLUM PSU + +PSU output current threshold is different for high line and low line +input. Using static threshold value doesn't allow thresholds +to be set based on input voltage. Update SOLUM configurtion file +to provide sensor label and scale factor to calculate threshold. +This allows thresholds to get updated on input voltage change. + +Tested: +Successfully able to build and pass through validate-configs.py. + +Signed-off-by: Vikash Chandola <vikash.chandola@intel.com> +Change-Id: I84e425f1e75ce04be96b70b8a91e90f7c796c9e8 +--- + configurations/PSSF162205A.json | 4 ++++ + configurations/SOLUM_PSSF162202_PSU.json | 4 ++++ + schemas/legacy.json | 8 ++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/configurations/PSSF162205A.json b/configurations/PSSF162205A.json +index d272ef1..7402947 100644 +--- a/configurations/PSSF162205A.json ++++ b/configurations/PSSF162205A.json +@@ -86,14 +86,18 @@ + "Direction": "greater than", + "Label": "iout1", + "Name": "upper critical", ++ "ScaleFactor": 0.001, + "Severity": 1, ++ "ThresholdLabel": "iout_oc_warn_limit", + "Value": 122 + }, + { + "Direction": "greater than", + "Label": "iout1", + "Name": "upper non critical", ++ "ScaleFactor": 0.00091, + "Severity": 0, ++ "ThresholdLabel": "iout_oc_warn_limit", + "Value": 100 + }, + { +diff --git a/configurations/SOLUM_PSSF162202_PSU.json b/configurations/SOLUM_PSSF162202_PSU.json +index c3ca25c..176a3d6 100644 +--- a/configurations/SOLUM_PSSF162202_PSU.json ++++ b/configurations/SOLUM_PSSF162202_PSU.json +@@ -145,14 +145,18 @@ + "Direction": "greater than", + "Label": "iout1", + "Name": "upper critical", ++ "ScaleFactor": 0.001, + "Severity": 1, ++ "ThresholdLabel": "iout_oc_warn_limit", + "Value": 122 + }, + { + "Direction": "greater than", + "Label": "iout1", + "Name": "upper non critical", ++ "ScaleFactor": 0.00091, + "Severity": 0, ++ "ThresholdLabel": "iout_oc_warn_limit", + "Value": 100 + }, + { +diff --git a/schemas/legacy.json b/schemas/legacy.json +index 47a6c7b..c3339ef 100644 +--- a/schemas/legacy.json ++++ b/schemas/legacy.json +@@ -698,6 +698,14 @@ + }, + "Value": { + "type": "number" ++ }, ++ "ThresholdLabel": { ++ "enum": [ ++ "iout_oc_warn_limit" ++ ] ++ }, ++ "ScaleFactor": { ++ "type": "number" + } + }, + "required": [ +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend index a8a9f17c5..181497547 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager_%.bbappend @@ -11,5 +11,6 @@ SRC_URI += " file://0001-fru-device-Add-MUX-channel-name-to-FRU-objects.patch \ file://0005-Allow-MUX-idle-state-to-be-configured-as-DISCONNECT.patch \ file://0006-Change-HSBP-FRU-address-and-add-MUX-mode-configurati.patch \ file://0007-Add-HSBP-FRU-details-in-json-configuration.patch \ + file://0008-dynamic-threshold-configuration-for-SOLUM-PSU.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/0001-add-Associations-endpoints-change-delay-timer.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/0001-add-Associations-endpoints-change-delay-timer.patch new file mode 100644 index 000000000..51afef80f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper/0001-add-Associations-endpoints-change-delay-timer.patch @@ -0,0 +1,978 @@ +From 48c39d798ce9683c186395272452893e2227d984 Mon Sep 17 00:00:00 2001 +From: "Kallas, Pawel" <pawel.kallas@intel.com> +Date: Mon, 9 Jan 2023 13:27:45 +0100 +Subject: [PATCH] add Associations endpoints change delay timer + +When multiple associations that point to the same interface are +created, each change (adding or removing one) leads to updating +"endpoints" property on dbus. This property update is time consuming +with many endpoints already present, because each update needs to send +the whole list of current elements plus/minus one. With a lot of +changes in short time it can cause the service to be unresponsive. +This change adds timer to delay updating dbus property. This way many +associations updates can be aggregated into single dbus property +update. + +Tested: Ran on hardware with dbus sensor tester. 4000 created sensors +with interfaces are processed within 10 seconds. Time before the change +was above 2 minutes. + +Signed-off-by: Kallas, Pawel <pawel.kallas@intel.com> +Change-Id: I1083c027ab12238249cffc67fb29a8ffef6baf83 +--- + src/associations.cpp | 156 ++++++++++++++++++++++------------ + src/associations.hpp | 32 +++++-- + src/main.cpp | 48 ++++++----- + src/processing.cpp | 13 +-- + src/processing.hpp | 6 +- + src/test/associations.cpp | 43 ++++++---- + src/test/interfaces_added.cpp | 6 +- + src/test/name_change.cpp | 10 ++- + 8 files changed, 202 insertions(+), 112 deletions(-) + +diff --git a/src/associations.cpp b/src/associations.cpp +index 9fd72ab..7730bbd 100644 +--- a/src/associations.cpp ++++ b/src/associations.cpp +@@ -1,10 +1,81 @@ + #include "associations.hpp" + + #include <boost/algorithm/string/predicate.hpp> ++#include <boost/asio/steady_timer.hpp> + #include <iostream> + #include <sdbusplus/exception.hpp> + +-void removeAssociation(const std::string& sourcePath, const std::string& owner, ++void updateEndpointsOnDbus(sdbusplus::asio::object_server& objectServer, ++ const std::string& assocPath, ++ AssociationMaps& assocMaps) ++{ ++ auto& iface = assocMaps.ifaces[assocPath]; ++ auto& i = std::get<ifacePos>(iface); ++ auto& endpoints = std::get<endpointsPos>(iface); ++ ++ // If the interface already exists, only need to update ++ // the property value, otherwise create it ++ if (i) ++ { ++ if (endpoints.empty()) ++ { ++ objectServer.remove_interface(i); ++ i = nullptr; ++ } ++ else ++ { ++ i->set_property("endpoints", endpoints); ++ } ++ } ++ else ++ { ++ if (!endpoints.empty()) ++ { ++ i = objectServer.add_interface(assocPath, ++ XYZ_ASSOCIATION_INTERFACE); ++ i->register_property("endpoints", endpoints); ++ i->initialize(); ++ } ++ } ++} ++ ++void scheduleUpdateEndpointsOnDbus(boost::asio::io_context& io, ++ sdbusplus::asio::object_server& objectServer, ++ const std::string& assocPath, ++ AssociationMaps& assocMaps) ++{ ++ static std::set<std::string> delayedUpdatePaths; ++ ++ if (delayedUpdatePaths.contains(assocPath)) ++ { ++ return; ++ } ++ ++ auto& iface = assocMaps.ifaces[assocPath]; ++ auto& endpoints = std::get<endpointsPos>(iface); ++ ++ if (endpoints.size() > endpointsCountTimerThreshold) ++ { ++ delayedUpdatePaths.emplace(assocPath); ++ auto timer = std::make_shared<boost::asio::steady_timer>( ++ io, std::chrono::seconds(endpointUpdateDelaySeconds)); ++ timer->async_wait([&objectServer, &assocMaps, timer, ++ assocPath](const boost::system::error_code& ec) { ++ if (!ec) ++ { ++ updateEndpointsOnDbus(objectServer, assocPath, assocMaps); ++ } ++ delayedUpdatePaths.erase(assocPath); ++ }); ++ } ++ else ++ { ++ updateEndpointsOnDbus(objectServer, assocPath, assocMaps); ++ } ++} ++ ++void removeAssociation(boost::asio::io_context& io, ++ const std::string& sourcePath, const std::string& owner, + sdbusplus::asio::object_server& server, + AssociationMaps& assocMaps) + { +@@ -34,7 +105,7 @@ void removeAssociation(const std::string& sourcePath, const std::string& owner, + + for (const auto& [assocPath, endpointsToRemove] : assocs->second) + { +- removeAssociationEndpoints(server, assocPath, endpointsToRemove, ++ removeAssociationEndpoints(io, server, assocPath, endpointsToRemove, + assocMaps); + } + +@@ -51,7 +122,8 @@ void removeAssociation(const std::string& sourcePath, const std::string& owner, + } + + void removeAssociationEndpoints( +- sdbusplus::asio::object_server& objectServer, const std::string& assocPath, ++ boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer, ++ const std::string& assocPath, + const boost::container::flat_set<std::string>& endpointsToRemove, + AssociationMaps& assocMaps) + { +@@ -74,22 +146,12 @@ void removeAssociationEndpoints( + } + } + +- if (endpointsInDBus.empty()) +- { +- objectServer.remove_interface(std::get<ifacePos>(assoc->second)); +- std::get<ifacePos>(assoc->second) = nullptr; +- std::get<endpointsPos>(assoc->second).clear(); +- } +- else +- { +- std::get<ifacePos>(assoc->second) +- ->set_property("endpoints", endpointsInDBus); +- } ++ scheduleUpdateEndpointsOnDbus(io, objectServer, assocPath, assocMaps); + } + + void checkAssociationEndpointRemoves( +- const std::string& sourcePath, const std::string& owner, +- const AssociationPaths& newAssociations, ++ boost::asio::io_context& io, const std::string& sourcePath, ++ const std::string& owner, const AssociationPaths& newAssociations, + sdbusplus::asio::object_server& objectServer, AssociationMaps& assocMaps) + { + // Find the services that have associations on this path. +@@ -118,7 +180,7 @@ void checkAssociationEndpointRemoves( + auto newEndpoints = newAssociations.find(originalAssocPath); + if (newEndpoints == newAssociations.end()) + { +- removeAssociationEndpoints(objectServer, originalAssocPath, ++ removeAssociationEndpoints(io, objectServer, originalAssocPath, + originalEndpoints, assocMaps); + } + else +@@ -138,7 +200,7 @@ void checkAssociationEndpointRemoves( + } + if (!toRemove.empty()) + { +- removeAssociationEndpoints(objectServer, originalAssocPath, ++ removeAssociationEndpoints(io, objectServer, originalAssocPath, + toRemove, assocMaps); + } + } +@@ -146,12 +208,12 @@ void checkAssociationEndpointRemoves( + } + + void addEndpointsToAssocIfaces( +- sdbusplus::asio::object_server& objectServer, const std::string& assocPath, ++ boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer, ++ const std::string& assocPath, + const boost::container::flat_set<std::string>& endpointPaths, + AssociationMaps& assocMaps) + { + auto& iface = assocMaps.ifaces[assocPath]; +- auto& i = std::get<ifacePos>(iface); + auto& endpoints = std::get<endpointsPos>(iface); + + // Only add new endpoints +@@ -162,22 +224,11 @@ void addEndpointsToAssocIfaces( + endpoints.push_back(e); + } + } +- +- // If the interface already exists, only need to update +- // the property value, otherwise create it +- if (i) +- { +- i->set_property("endpoints", endpoints); +- } +- else +- { +- i = objectServer.add_interface(assocPath, XYZ_ASSOCIATION_INTERFACE); +- i->register_property("endpoints", endpoints); +- i->initialize(); +- } ++ scheduleUpdateEndpointsOnDbus(io, objectServer, assocPath, assocMaps); + } + +-void associationChanged(sdbusplus::asio::object_server& objectServer, ++void associationChanged(boost::asio::io_context& io, ++ sdbusplus::asio::object_server& objectServer, + const std::vector<Association>& associations, + const std::string& path, const std::string& owner, + const interface_map_type& interfaceMap, +@@ -217,12 +268,12 @@ void associationChanged(sdbusplus::asio::object_server& objectServer, + } + for (const auto& object : objects) + { +- addEndpointsToAssocIfaces(objectServer, object.first, object.second, ++ addEndpointsToAssocIfaces(io, objectServer, object.first, object.second, + assocMaps); + } + + // Check for endpoints being removed instead of added +- checkAssociationEndpointRemoves(path, owner, objects, objectServer, ++ checkAssociationEndpointRemoves(io, path, owner, objects, objectServer, + assocMaps); + + if (!objects.empty()) +@@ -312,7 +363,8 @@ void removeFromPendingAssociations(const std::string& endpointPath, + } + } + +-void addSingleAssociation(sdbusplus::asio::object_server& server, ++void addSingleAssociation(boost::asio::io_context& io, ++ sdbusplus::asio::object_server& server, + const std::string& assocPath, + const std::string& endpoint, const std::string& owner, + const std::string& ownerPath, +@@ -320,7 +372,7 @@ void addSingleAssociation(sdbusplus::asio::object_server& server, + { + boost::container::flat_set<std::string> endpoints{endpoint}; + +- addEndpointsToAssocIfaces(server, assocPath, endpoints, assocMaps); ++ addEndpointsToAssocIfaces(io, server, assocPath, endpoints, assocMaps); + + AssociationPaths objects; + boost::container::flat_set e{endpoint}; +@@ -355,7 +407,8 @@ void addSingleAssociation(sdbusplus::asio::object_server& server, + } + } + +-void checkIfPendingAssociation(const std::string& objectPath, ++void checkIfPendingAssociation(boost::asio::io_context& io, ++ const std::string& objectPath, + const interface_map_type& interfaceMap, + AssociationMaps& assocMaps, + sdbusplus::asio::object_server& server) +@@ -399,13 +452,13 @@ void checkIfPendingAssociation(const std::string& objectPath, + + try + { +- addSingleAssociation(server, assocPath, endpointPath, owner, ++ addSingleAssociation(io, server, assocPath, endpointPath, owner, + ownerPath, assocMaps); + + // Now the reverse direction (still the same owner and ownerPath) + assocPath = endpointPath + '/' + std::get<reverseTypePos>(e); + endpointPath = objectPath; +- addSingleAssociation(server, assocPath, endpointPath, owner, ++ addSingleAssociation(io, server, assocPath, endpointPath, owner, + ownerPath, assocMaps); + } + catch (const sdbusplus::exception::exception& e) +@@ -495,7 +548,8 @@ void findAssociations(const std::string& endpointPath, + * @param[in,out] assocMaps - the association maps + * @param[in,out] server - sdbus system object + */ +-void removeAssociationIfacesEntry(const std::string& assocPath, ++void removeAssociationIfacesEntry(boost::asio::io_context& io, ++ const std::string& assocPath, + const std::string& endpointPath, + AssociationMaps& assocMaps, + sdbusplus::asio::object_server& server) +@@ -509,16 +563,7 @@ void removeAssociationIfacesEntry(const std::string& assocPath, + { + endpoints.erase(e); + +- if (endpoints.empty()) +- { +- server.remove_interface(std::get<ifacePos>(assoc->second)); +- std::get<ifacePos>(assoc->second) = nullptr; +- } +- else +- { +- std::get<ifacePos>(assoc->second) +- ->set_property("endpoints", endpoints); +- } ++ scheduleUpdateEndpointsOnDbus(io, server, assocPath, assocMaps); + } + } + } +@@ -577,7 +622,8 @@ void removeAssociationOwnersEntry(const std::string& assocPath, + } + } + +-void moveAssociationToPending(const std::string& endpointPath, ++void moveAssociationToPending(boost::asio::io_context& io, ++ const std::string& endpointPath, + AssociationMaps& assocMaps, + sdbusplus::asio::object_server& server) + { +@@ -599,9 +645,9 @@ void moveAssociationToPending(const std::string& endpointPath, + reverseType, owner, assocMaps); + + // Remove both sides of the association from assocMaps.ifaces +- removeAssociationIfacesEntry(forwardPath + '/' + forwardType, ++ removeAssociationIfacesEntry(io, forwardPath + '/' + forwardType, + reversePath, assocMaps, server); +- removeAssociationIfacesEntry(reversePath + '/' + reverseType, ++ removeAssociationIfacesEntry(io, reversePath + '/' + reverseType, + forwardPath, assocMaps, server); + + // Remove both sides of the association from assocMaps.owners +diff --git a/src/associations.hpp b/src/associations.hpp +index dd6cbdb..b4ee91b 100644 +--- a/src/associations.hpp ++++ b/src/associations.hpp +@@ -5,8 +5,12 @@ + constexpr const char* XYZ_ASSOCIATION_INTERFACE = + "xyz.openbmc_project.Association"; + ++constexpr size_t endpointsCountTimerThreshold = 100; ++constexpr int endpointUpdateDelaySeconds = 1; ++ + /** @brief Remove input association + * ++ * @param[in] io - io context + * @param[in] sourcePath - Path of the object that contains the + * org.openbmc.Associations + * @param[in] owner - The Dbus service having its associations +@@ -16,7 +20,8 @@ constexpr const char* XYZ_ASSOCIATION_INTERFACE = + * + * @return Void, server, assocMaps updated if needed + */ +-void removeAssociation(const std::string& sourcePath, const std::string& owner, ++void removeAssociation(boost::asio::io_context& io, ++ const std::string& sourcePath, const std::string& owner, + sdbusplus::asio::object_server& server, + AssociationMaps& assocMaps); + +@@ -25,6 +30,7 @@ void removeAssociation(const std::string& sourcePath, const std::string& owner, + * If the last endpoint was removed, then remove the whole + * association object, otherwise just set the property + * ++ * @param[in] io - io context + * @param[in] objectServer - sdbus system object + * @param[in] assocPath - Path of the object that contains the + * org.openbmc.Associations +@@ -34,7 +40,8 @@ void removeAssociation(const std::string& sourcePath, const std::string& owner, + * @return Void, objectServer and assocMaps updated if needed + */ + void removeAssociationEndpoints( +- sdbusplus::asio::object_server& objectServer, const std::string& assocPath, ++ boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer, ++ const std::string& assocPath, + const boost::container::flat_set<std::string>& endpointsToRemove, + AssociationMaps& assocMaps); + +@@ -47,6 +54,7 @@ void removeAssociationEndpoints( + * from the endpoints property, remove that whole association object from + * D-Bus. + * ++ * @param[in] io - io context + * @param[in] sourcePath - Path of the object that contains the + * org.openbmc.Associations + * @param[in] owner - The Dbus service having it's associatons +@@ -58,8 +66,8 @@ void removeAssociationEndpoints( + * @return Void, objectServer and assocMaps updated if needed + */ + void checkAssociationEndpointRemoves( +- const std::string& sourcePath, const std::string& owner, +- const AssociationPaths& newAssociations, ++ boost::asio::io_context& io, const std::string& sourcePath, ++ const std::string& owner, const AssociationPaths& newAssociations, + sdbusplus::asio::object_server& objectServer, AssociationMaps& assocMaps); + + /** @brief Handle new or changed association interfaces +@@ -67,6 +75,7 @@ void checkAssociationEndpointRemoves( + * Called when either a new org.openbmc.Associations interface was + * created, or the associations property on that interface changed + * ++ * @param[in] io - io context + * @param[in,out] objectServer - sdbus system object + * @param[in] associations - New associations to look at for change + * @param[in] path - Path of the object that contains the +@@ -78,7 +87,8 @@ void checkAssociationEndpointRemoves( + * + * @return Void, objectServer and assocMaps updated if needed + */ +-void associationChanged(sdbusplus::asio::object_server& objectServer, ++void associationChanged(boost::asio::io_context& io, ++ sdbusplus::asio::object_server& objectServer, + const std::vector<Association>& associations, + const std::string& path, const std::string& owner, + const interface_map_type& interfaceMap, +@@ -123,6 +133,7 @@ void removeFromPendingAssociations(const std::string& endpointPath, + + /** @brief Adds a single association D-Bus object (<path>/<type>) + * ++ * @param[in] io - io context + * @param[in,out] server - sdbus system object + * @param[in] assocPath - The association D-Bus path + * @param[in] endpoint - The association's D-Bus endpoint path +@@ -130,7 +141,8 @@ void removeFromPendingAssociations(const std::string& endpointPath, + * @param[in] ownerPath - The D-Bus path hosting the Associations property + * @param[in,out] assocMaps - The association maps + */ +-void addSingleAssociation(sdbusplus::asio::object_server& server, ++void addSingleAssociation(boost::asio::io_context& io, ++ sdbusplus::asio::object_server& server, + const std::string& assocPath, + const std::string& endpoint, const std::string& owner, + const std::string& ownerPath, +@@ -143,12 +155,14 @@ void addSingleAssociation(sdbusplus::asio::object_server& server, + * map, create the 2 real association objects and remove its pending + * associations entry. Used when a new path shows up in D-Bus. + * ++ * @param[in] io - io context + * @param[in] objectPath - the path to check + * @param[in] interfaceMap - The master interface map + * @param[in,out] assocMaps - The association maps + * @param[in,out] server - sdbus system object + */ +-void checkIfPendingAssociation(const std::string& objectPath, ++void checkIfPendingAssociation(boost::asio::io_context& io, ++ const std::string& objectPath, + const interface_map_type& interfaceMap, + AssociationMaps& assocMaps, + sdbusplus::asio::object_server& server); +@@ -172,10 +186,12 @@ void findAssociations(const std::string& endpointPath, + * association endpoint (the path that owns the association is still + * on D-Bus), then move the association it's involved in to pending. + * ++ * @param[in] io - io context + * @param[in] endpointPath - the D-Bus endpoint path to check + * @param[in,out] assocMaps - The association maps + * @param[in,out] server - sdbus system object + */ +-void moveAssociationToPending(const std::string& endpointPath, ++void moveAssociationToPending(boost::asio::io_context& io, ++ const std::string& endpointPath, + AssociationMaps& assocMaps, + sdbusplus::asio::object_server& server); +diff --git a/src/main.cpp b/src/main.cpp +index 53b36d5..ee03be7 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -131,7 +131,8 @@ struct InProgressIntrospect + #endif + }; + +-void do_associations(sdbusplus::asio::connection* system_bus, ++void do_associations(boost::asio::io_context& io, ++ sdbusplus::asio::connection* system_bus, + interface_map_type& interfaceMap, + sdbusplus::asio::object_server& objectServer, + const std::string& processName, const std::string& path, +@@ -139,7 +140,7 @@ void do_associations(sdbusplus::asio::connection* system_bus, + { + constexpr int maxTimeoutRetries = 3; + system_bus->async_method_call( +- [&objectServer, path, processName, &interfaceMap, system_bus, ++ [&io, &objectServer, path, processName, &interfaceMap, system_bus, + timeoutRetries]( + const boost::system::error_code ec, + const std::variant<std::vector<Association>>& variantAssociations) { +@@ -148,7 +149,7 @@ void do_associations(sdbusplus::asio::connection* system_bus, + if (ec.value() == boost::system::errc::timed_out && + timeoutRetries < maxTimeoutRetries) + { +- do_associations(system_bus, interfaceMap, objectServer, ++ do_associations(io, system_bus, interfaceMap, objectServer, + processName, path, timeoutRetries + 1); + return; + } +@@ -156,14 +157,15 @@ void do_associations(sdbusplus::asio::connection* system_bus, + } + std::vector<Association> associations = + std::get<std::vector<Association>>(variantAssociations); +- associationChanged(objectServer, associations, path, processName, +- interfaceMap, associationMaps); ++ associationChanged(io, objectServer, associations, path, ++ processName, interfaceMap, associationMaps); + }, + processName, path, "org.freedesktop.DBus.Properties", "Get", + assocDefsInterface, assocDefsProperty); + } + +-void do_introspect(sdbusplus::asio::connection* system_bus, ++void do_introspect(boost::asio::io_context& io, ++ sdbusplus::asio::connection* system_bus, + std::shared_ptr<InProgressIntrospect> transaction, + interface_map_type& interface_map, + sdbusplus::asio::object_server& objectServer, +@@ -171,7 +173,7 @@ void do_introspect(sdbusplus::asio::connection* system_bus, + { + constexpr int maxTimeoutRetries = 3; + system_bus->async_method_call( +- [&interface_map, &objectServer, transaction, path, system_bus, ++ [&io, &interface_map, &objectServer, transaction, path, system_bus, + timeoutRetries](const boost::system::error_code ec, + const std::string& introspect_xml) { + if (ec) +@@ -179,7 +181,7 @@ void do_introspect(sdbusplus::asio::connection* system_bus, + if (ec.value() == boost::system::errc::timed_out && + timeoutRetries < maxTimeoutRetries) + { +- do_introspect(system_bus, transaction, interface_map, ++ do_introspect(io, system_bus, transaction, interface_map, + objectServer, path, timeoutRetries + 1); + return; + } +@@ -220,7 +222,7 @@ void do_introspect(sdbusplus::asio::connection* system_bus, + + if (std::strcmp(iface_name, assocDefsInterface) == 0) + { +- do_associations(system_bus, interface_map, objectServer, ++ do_associations(io, system_bus, interface_map, objectServer, + transaction->process_name, path); + } + +@@ -229,7 +231,7 @@ void do_introspect(sdbusplus::asio::connection* system_bus, + + // Check if this new path has a pending association that can + // now be completed. +- checkIfPendingAssociation(path, interface_map, ++ checkIfPendingAssociation(io, path, interface_map, + transaction->assocMaps, objectServer); + + pElement = pRoot->FirstChildElement("node"); +@@ -244,7 +246,7 @@ void do_introspect(sdbusplus::asio::connection* system_bus, + parent_path.clear(); + } + +- do_introspect(system_bus, transaction, interface_map, ++ do_introspect(io, system_bus, transaction, interface_map, + objectServer, parent_path + "/" + child_path); + } + pElement = pElement->NextSiblingElement("node"); +@@ -275,7 +277,7 @@ void start_new_introspect( + #endif + ); + +- do_introspect(system_bus, transaction, interface_map, objectServer, ++ do_introspect(io, system_bus, transaction, interface_map, objectServer, + "/"); + } + } +@@ -684,7 +686,7 @@ int main(int argc, char** argv) + + if (!old_owner.empty()) + { +- processNameChangeDelete(name_owners, name, old_owner, ++ processNameChangeDelete(io, name_owners, name, old_owner, + interface_map, associationMaps, server); + } + +@@ -715,7 +717,7 @@ int main(int argc, char** argv) + sdbusplus::bus::match::rules::nameOwnerChanged(), nameChangeHandler); + + std::function<void(sdbusplus::message::message & message)> +- interfacesAddedHandler = [&interface_map, &name_owners, &server]( ++ interfacesAddedHandler = [&io, &interface_map, &name_owners, &server]( + sdbusplus::message::message& message) { + sdbusplus::message::object_path obj_path; + InterfacesAdded interfaces_added; +@@ -728,8 +730,9 @@ int main(int argc, char** argv) + if (needToIntrospect(well_known, service_whitelist, + service_blacklist)) + { +- processInterfaceAdded(interface_map, obj_path, interfaces_added, +- well_known, associationMaps, server); ++ processInterfaceAdded(io, interface_map, obj_path, ++ interfaces_added, well_known, ++ associationMaps, server); + } + }; + +@@ -739,7 +742,7 @@ int main(int argc, char** argv) + interfacesAddedHandler); + + std::function<void(sdbusplus::message::message & message)> +- interfacesRemovedHandler = [&interface_map, &name_owners, &server]( ++ interfacesRemovedHandler = [&io, &interface_map, &name_owners, &server]( + sdbusplus::message::message& message) { + sdbusplus::message::object_path obj_path; + std::vector<std::string> interfaces_removed; +@@ -765,7 +768,7 @@ int main(int argc, char** argv) + + if (interface == assocDefsInterface) + { +- removeAssociation(obj_path.str, sender, server, ++ removeAssociation(io, obj_path.str, sender, server, + associationMaps); + } + +@@ -788,8 +791,8 @@ int main(int argc, char** argv) + { + // Remove the 2 association D-Bus paths and move the + // association to pending. +- moveAssociationToPending(obj_path.str, associationMaps, +- server); ++ moveAssociationToPending(io, obj_path.str, ++ associationMaps, server); + } + } + } +@@ -809,7 +812,8 @@ int main(int argc, char** argv) + interfacesRemovedHandler); + + std::function<void(sdbusplus::message::message & message)> +- associationChangedHandler = [&server, &name_owners, &interface_map]( ++ associationChangedHandler = [&io, &server, &name_owners, ++ &interface_map]( + sdbusplus::message::message& message) { + std::string objectName; + boost::container::flat_map<std::string, +@@ -828,7 +832,7 @@ int main(int argc, char** argv) + { + return; + } +- associationChanged(server, associations, message.get_path(), ++ associationChanged(io, server, associations, message.get_path(), + well_known, interface_map, associationMaps); + } + }; +diff --git a/src/processing.cpp b/src/processing.cpp +index f144b77..5e61fbc 100644 +--- a/src/processing.cpp ++++ b/src/processing.cpp +@@ -40,6 +40,7 @@ bool needToIntrospect(const std::string& processName, + } + + void processNameChangeDelete( ++ boost::asio::io_context& io, + boost::container::flat_map<std::string, std::string>& nameOwners, + const std::string& wellKnown, const std::string& oldOwner, + interface_map_type& interfaceMap, AssociationMaps& assocMaps, +@@ -67,7 +68,8 @@ void processNameChangeDelete( + assocDefsInterface); + if (assoc != ifaces->second.end()) + { +- removeAssociation(pathIt->first, wellKnown, server, assocMaps); ++ removeAssociation(io, pathIt->first, wellKnown, server, ++ assocMaps); + } + + // Instead of checking if every single path is the endpoint of an +@@ -80,7 +82,7 @@ void processNameChangeDelete( + { + // Remove the 2 association D-Bus paths and move the + // association to pending. +- moveAssociationToPending(pathIt->first, assocMaps, server); ++ moveAssociationToPending(io, pathIt->first, assocMaps, server); + } + } + pathIt->second.erase(wellKnown); +@@ -95,7 +97,8 @@ void processNameChangeDelete( + } + } + +-void processInterfaceAdded(interface_map_type& interfaceMap, ++void processInterfaceAdded(boost::asio::io_context& io, ++ interface_map_type& interfaceMap, + const sdbusplus::message::object_path& objPath, + const InterfacesAdded& intfAdded, + const std::string& wellKnown, +@@ -127,7 +130,7 @@ void processInterfaceAdded(interface_map_type& interfaceMap, + } + std::vector<Association> associations = + std::get<std::vector<Association>>(*variantAssociations); +- associationChanged(server, associations, objPath.str, wellKnown, ++ associationChanged(io, server, associations, objPath.str, wellKnown, + interfaceMap, assocMaps); + } + } +@@ -178,5 +181,5 @@ void processInterfaceAdded(interface_map_type& interfaceMap, + } + + // The new interface might have an association pending +- checkIfPendingAssociation(objPath.str, interfaceMap, assocMaps, server); ++ checkIfPendingAssociation(io, objPath.str, interfaceMap, assocMaps, server); + } +diff --git a/src/processing.hpp b/src/processing.hpp +index 114b502..98be262 100644 +--- a/src/processing.hpp ++++ b/src/processing.hpp +@@ -60,6 +60,7 @@ bool needToIntrospect(const std::string& processName, + + /** @brief Handle the removal of an existing name in objmgr data structures + * ++ * @param[in] io - io context + * @param[in,out] nameOwners - Map of unique name to well known name + * @param[in] wellKnown - Well known name that has new owner + * @param[in] oldOwner - Old unique name +@@ -69,6 +70,7 @@ bool needToIntrospect(const std::string& processName, + * + */ + void processNameChangeDelete( ++ boost::asio::io_context& io, + boost::container::flat_map<std::string, std::string>& nameOwners, + const std::string& wellKnown, const std::string& oldOwner, + interface_map_type& interfaceMap, AssociationMaps& assocMaps, +@@ -76,6 +78,7 @@ void processNameChangeDelete( + + /** @brief Handle an interfaces added signal + * ++ * @param[in] io - io context + * @param[in,out] interfaceMap - Global map of interfaces + * @param[in] objPath - New path to process + * @param[in] interfacesAdded - New interfaces to process +@@ -84,7 +87,8 @@ void processNameChangeDelete( + * @param[in,out] server - sdbus system object + * + */ +-void processInterfaceAdded(interface_map_type& interfaceMap, ++void processInterfaceAdded(boost::asio::io_context& io, ++ interface_map_type& interfaceMap, + const sdbusplus::message::object_path& objPath, + const InterfacesAdded& intfAdded, + const std::string& wellKnown, +diff --git a/src/test/associations.cpp b/src/test/associations.cpp +index 73c36ed..f019a76 100644 +--- a/src/test/associations.cpp ++++ b/src/test/associations.cpp +@@ -11,6 +11,12 @@ + + class TestAssociations : public AsioServerClassTest + { ++ public: ++ boost::asio::io_context io; ++ virtual void SetUp() ++ { ++ io.run(); ++ } + }; + sdbusplus::asio::object_server* TestAssociations::AsioServerClassTest::server = + nullptr; +@@ -22,7 +28,7 @@ TEST_F(TestAssociations, SourcePathNotInAssociations) + std::string sourcePath = "/xyz/openbmc_project/no/association"; + AssociationMaps assocMaps; + +- removeAssociation(sourcePath, DEFAULT_DBUS_SVC, *server, assocMaps); ++ removeAssociation(io, sourcePath, DEFAULT_DBUS_SVC, *server, assocMaps); + } + + // Verify call when owner is not in associated owners +@@ -31,7 +37,7 @@ TEST_F(TestAssociations, OwnerNotInAssociations) + AssociationMaps assocMaps; + assocMaps.owners = createDefaultOwnerAssociation(); + +- removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, ++ removeAssociation(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, + assocMaps); + } + +@@ -42,7 +48,7 @@ TEST_F(TestAssociations, PathNotInAssocInterfaces) + + assocMaps.owners = createDefaultOwnerAssociation(); + +- removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, ++ removeAssociation(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, + assocMaps); + + EXPECT_TRUE(assocMaps.owners.empty()); +@@ -57,7 +63,7 @@ TEST_F(TestAssociations, PathIsInAssociatedInterfaces) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, ++ removeAssociation(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, + assocMaps); + + // Verify owner association was deleted +@@ -83,7 +89,7 @@ TEST_F(TestAssociations, PathIsInAssociatedInterfacesExtraEndpoints) + // Add another endpoint to the assoc interfaces + addEndpointToInterfaceAssociation(assocMaps.ifaces); + +- removeAssociation(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, ++ removeAssociation(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, *server, + assocMaps); + + // Verify owner association was deleted +@@ -109,7 +115,7 @@ TEST_F(TestAssociations, checkAssociationEndpointRemovesNoEpRemove) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, ++ checkAssociationEndpointRemoves(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, + newAssocPaths, *server, assocMaps); + + // Verify endpoints were not deleted because they matche with what was +@@ -130,7 +136,7 @@ TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveApDiff) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, ++ checkAssociationEndpointRemoves(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, + newAssocPaths, *server, assocMaps); + + // Verify initial endpoints were deleted because the new path +@@ -152,7 +158,7 @@ TEST_F(TestAssociations, checkAssociationEndpointRemovesEpRemoveEpChanged) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- checkAssociationEndpointRemoves(DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, ++ checkAssociationEndpointRemoves(io, DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, + newAssocPaths, *server, assocMaps); + + // Verify initial endpoints were deleted because of different endpoints +@@ -175,7 +181,7 @@ TEST_F(TestAssociations, associationChangedEmptyEndpoint) + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + + // Empty endpoint will result in deletion of corresponding assocInterface +- associationChanged(*server, associations, DEFAULT_SOURCE_PATH, ++ associationChanged(io, *server, associations, DEFAULT_SOURCE_PATH, + DEFAULT_DBUS_SVC, interfaceMap, assocMaps); + + // Both of these should be 0 since we have an invalid endpoint +@@ -203,7 +209,7 @@ TEST_F(TestAssociations, associationChangedAddNewAssoc) + {"/new/source/path", {{DEFAULT_DBUS_SVC, {"a"}}}}, + {"/xyz/openbmc_project/new/endpoint", {{DEFAULT_DBUS_SVC, {"a"}}}}}; + +- associationChanged(*server, associations, "/new/source/path", ++ associationChanged(io, *server, associations, "/new/source/path", + DEFAULT_DBUS_SVC, interfaceMap, assocMaps); + + // Two source paths +@@ -237,7 +243,7 @@ TEST_F(TestAssociations, associationChangedAddNewAssocEmptyObj) + // Make it look like the assoc endpoints are on D-Bus + interface_map_type interfaceMap = createDefaultInterfaceMap(); + +- associationChanged(*server, associations, DEFAULT_SOURCE_PATH, ++ associationChanged(io, *server, associations, DEFAULT_SOURCE_PATH, + DEFAULT_DBUS_SVC, interfaceMap, assocMaps); + + // New associations so ensure it now contains a single entry +@@ -273,7 +279,7 @@ TEST_F(TestAssociations, associationChangedAddNewAssocNewOwner) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- associationChanged(*server, associations, DEFAULT_SOURCE_PATH, newOwner, ++ associationChanged(io, *server, associations, DEFAULT_SOURCE_PATH, newOwner, + interfaceMap, assocMaps); + + // New endpoint so assocOwners should be same size +@@ -306,7 +312,7 @@ TEST_F(TestAssociations, associationChangedAddNewAssocSameInterface) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- associationChanged(*server, associations, DEFAULT_SOURCE_PATH, ++ associationChanged(io, *server, associations, DEFAULT_SOURCE_PATH, + DEFAULT_DBUS_SVC, interfaceMap, assocMaps); + + // Should have 3 entries in AssociationInterfaces, one is just missing an +@@ -406,7 +412,7 @@ TEST_F(TestAssociations, associationChangedPending) + AssociationMaps assocMaps; + interface_map_type interfaceMap; + +- associationChanged(*server, associations, "/new/source/path", ++ associationChanged(io, *server, associations, "/new/source/path", + DEFAULT_DBUS_SVC, interfaceMap, assocMaps); + + // No associations were actually added +@@ -460,7 +466,7 @@ TEST_F(TestAssociations, checkIfPending) + EXPECT_EQ(assocMaps.pending.size(), 1); + + // Move the pending association to a real association +- checkIfPendingAssociation(DEFAULT_SOURCE_PATH, interfaceMap, assocMaps, ++ checkIfPendingAssociation(io, DEFAULT_SOURCE_PATH, interfaceMap, assocMaps, + *server); + + EXPECT_TRUE(assocMaps.pending.empty()); +@@ -468,7 +474,8 @@ TEST_F(TestAssociations, checkIfPending) + EXPECT_EQ(assocMaps.ifaces.size(), 2); + + // This shouldn't do anything, since /new/path isn't pending +- checkIfPendingAssociation("/new/path", interfaceMap, assocMaps, *server); ++ checkIfPendingAssociation(io, "/new/path", interfaceMap, assocMaps, ++ *server); + EXPECT_TRUE(assocMaps.pending.empty()); + EXPECT_EQ(assocMaps.owners.size(), 1); + EXPECT_EQ(assocMaps.ifaces.size(), 2); +@@ -525,7 +532,7 @@ TEST_F(TestAssociations, moveAssocToPendingNoOp) + AssociationMaps assocMaps; + + // Not an association, so it shouldn't do anything +- moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server); ++ moveAssociationToPending(io, DEFAULT_ENDPOINT, assocMaps, *server); + + EXPECT_TRUE(assocMaps.pending.empty()); + EXPECT_TRUE(assocMaps.owners.empty()); +@@ -538,7 +545,7 @@ TEST_F(TestAssociations, moveAssocToPending) + assocMaps.owners = createDefaultOwnerAssociation(); + assocMaps.ifaces = createDefaultInterfaceAssociation(server); + +- moveAssociationToPending(DEFAULT_ENDPOINT, assocMaps, *server); ++ moveAssociationToPending(io, DEFAULT_ENDPOINT, assocMaps, *server); + + // Check it's now pending + EXPECT_EQ(assocMaps.pending.size(), 1); +diff --git a/src/test/interfaces_added.cpp b/src/test/interfaces_added.cpp +index ee0e438..14cdc85 100644 +--- a/src/test/interfaces_added.cpp ++++ b/src/test/interfaces_added.cpp +@@ -38,9 +38,13 @@ TEST_F(TestInterfacesAdded, InterfacesAddedGoodPath) + auto intfAdded = + createInterfacesAdded(assocDefsInterface, assocDefsProperty); + +- processInterfaceAdded(interfaceMap, DEFAULT_SOURCE_PATH, intfAdded, ++ boost::asio::io_context io; ++ ++ processInterfaceAdded(io, interfaceMap, DEFAULT_SOURCE_PATH, intfAdded, + DEFAULT_DBUS_SVC, assocMaps, *server); + ++ io.run(); ++ + // Interface map will get the following: + // /logging/entry/1 /logging/entry /logging/ / system/chassis + // dump_InterfaceMapType(interfaceMap); +diff --git a/src/test/name_change.cpp b/src/test/name_change.cpp +index 95d02af..3ac4e41 100644 +--- a/src/test/name_change.cpp ++++ b/src/test/name_change.cpp +@@ -6,6 +6,12 @@ + + class TestNameChange : public AsioServerClassTest + { ++ public: ++ boost::asio::io_context io; ++ virtual void SetUp() ++ { ++ io.run(); ++ } + }; + sdbusplus::asio::object_server* TestNameChange::AsioServerClassTest::server = + nullptr; +@@ -20,7 +26,7 @@ TEST_F(TestNameChange, UniqueNameNoInterfaces) + interface_map_type interfaceMap; + AssociationMaps assocMaps; + +- processNameChangeDelete(nameOwners, wellKnown, oldOwner, interfaceMap, ++ processNameChangeDelete(io, nameOwners, wellKnown, oldOwner, interfaceMap, + assocMaps, *server); + EXPECT_EQ(nameOwners.size(), 0); + } +@@ -42,7 +48,7 @@ TEST_F(TestNameChange, UniqueNameAssociationsAndInterface) + auto interfaceMap = createInterfaceMap( + DEFAULT_SOURCE_PATH, DEFAULT_DBUS_SVC, assocInterfacesSet); + +- processNameChangeDelete(nameOwners, DEFAULT_DBUS_SVC, oldOwner, ++ processNameChangeDelete(io, nameOwners, DEFAULT_DBUS_SVC, oldOwner, + interfaceMap, assocMaps, *server); + EXPECT_EQ(nameOwners.size(), 0); + +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend index 4fc41d058..05e9fec1b 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/dbus/phosphor-mapper_%.bbappend @@ -1 +1,3 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" + +SRC_URI += "file://0001-add-Associations-endpoints-change-delay-timer.patch" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd/0001-Avoid-negated-postcode-write-to-D-Bus.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd/0001-Avoid-negated-postcode-write-to-D-Bus.patch new file mode 100644 index 000000000..47afc4568 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd/0001-Avoid-negated-postcode-write-to-D-Bus.patch @@ -0,0 +1,58 @@ +From 3311e449da0c7431f5512138aa61212af3d769a1 Mon Sep 17 00:00:00 2001 +From: Zhikui Ren <zhikui.ren@intel.com> +Date: Mon, 14 Nov 2022 14:14:33 -0800 +Subject: [PATCH] Avoid negated postcode write to D-Bus + +This commit removes the code which writes the negated +postcode value to D-Bus object. This has some side effects +when bombarded data pushed to port 80. + +With this change, if same post code is written on LPC channel +it will be set but D-Bus will not emit the 'PropertiesChanged' +signal. Actually there is no need to emit the signal if actual +property value(postcode) is not changed. + +So if post code changes, D-Bus will emit the signal as usual +with this code. Any client applications depends on this, still +can register for signal for knowing postcode change. + +Renamed bbappend file for generic notation. + +Tested: + - Manually verified by setting different post code, + emits the signal. + + busctl set-property xyz.openbmc_project.State.Boot.Raw + /xyz/openbmc_project/state/boot/raw0 xyz.openbmc_project.State.Boot.Raw + Value t 00 + + dbus-monitor --system "type='signal',member='PropertiesChanged', + interface='org.freedesktop.DBus.Properties', + path_namespace=/xyz/openbmc_project/state/boot/raw0, + arg0=xyz.openbmc_project.State.Boot.Raw" + + - Verified functionality with real post code changes. + +Change-Id: I13e7879a19ada593891821df3702613cc8e84572 +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +Signed-off-by: Zhikui Ren <zhikui.ren@intel.com> +--- + main.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/main.cpp b/main.cpp +index 3a3b4ce..764c855 100644 +--- a/main.cpp ++++ b/main.cpp +@@ -66,7 +66,7 @@ void PostCodeEventHandler(sdeventplus::source::IO& s, int postFd, uint32_t, + // HACK: Always send property changed signal even for the same code + // since we are single threaded, external users will never see the + // first value. +- reporter->value(std::make_tuple(~code, secondary_post_code_t{}), true); ++ // reporter->value(std::make_tuple(~code, secondary_post_code_t{}), true); + reporter->value(std::make_tuple(code, secondary_post_code_t{})); + + // read depends on old data being cleared since it doens't always read +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend new file mode 100644 index 000000000..893f410e8 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend @@ -0,0 +1,9 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:" +PROJECT_SRC_DIR := "${THISDIR}/${PN}" + +DEPENDS += " gtest" + +#SRC_URI = "git://github.com/openbmc/phosphor-host-postd.git" +SRCREV = "6a5e0a1cba979c3c793e794c41481221da9a4e33" + +SRC_URI += "file://0001-Avoid-negated-postcode-write-to-D-Bus.patch" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend deleted file mode 100644 index 21ff75f73..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend +++ /dev/null @@ -1,4 +0,0 @@ -DEPENDS += " gtest" - -#SRC_URI = "git://github.com/openbmc/phosphor-host-postd.git" -SRCREV = "6a5e0a1cba979c3c793e794c41481221da9a4e33" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0009-virtual_media-Fix-for-bmcweb-crash.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0009-virtual_media-Fix-for-bmcweb-crash.patch new file mode 100644 index 000000000..a2a120c22 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/vm/0009-virtual_media-Fix-for-bmcweb-crash.patch @@ -0,0 +1,47 @@ +From 348186f045f23d59405ac0011e983aea8334598a Mon Sep 17 00:00:00 2001 +From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +Date: Thu, 4 May 2023 13:56:27 +0000 +Subject: [PATCH] virtual_media: Fix for bmcweb crash + +This is ported from main line. +https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62593 + +bmcweb crashes when user not providing userName or password while +posting ISO form Redfish. + +This fix provides to avoid bmcweb crash when user try to post ISO images +from Redfish without providing username or password. + +Tested: +Redfish validator passed with this change. +Verified by Posting ISO from Redfish. + +Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +--- + redfish-core/lib/virtual_media.hpp | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp +index 6dfc726b..838a08b1 100644 +--- a/redfish-core/lib/virtual_media.hpp ++++ b/redfish-core/lib/virtual_media.hpp +@@ -1069,6 +1069,16 @@ inline void requestNBDVirtualMediaRoutes(App& app) + return true; + } + ++ if (!actionParams.userName) ++ { ++ actionParams.userName = ""; ++ } ++ ++ if (!actionParams.password) ++ { ++ actionParams.password = ""; ++ } ++ + // manager is irrelevant for + // VirtualMedia dbus calls + doMountVmLegacy(asyncResp, service, resName, +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend index d5e7a6dd2..e3bed9eb0 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend @@ -55,6 +55,7 @@ SRC_URI += " \ file://vm/0006-Bmcweb-handle-permission-denied-exception.patch \ file://vm/0007-Fix-unmounting-image-in-proxy-mode.patch \ file://vm/0008-Return-404-for-POST-on-Proxy-InsertMedia.patch \ + file://vm/0009-virtual_media-Fix-for-bmcweb-crash.patch \ " # EventService: Temporary pulled to downstream. See eventservice\README for details diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb index bdc85913f..5ddca8730 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb @@ -5,7 +5,7 @@ LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e" SRC_URI = "git://git@github.com/Intel-BMC/mctpd.git;protocol=ssh;branch=1-release" -SRCREV = "4aa697fba21a2d0d0770358a8c9493bf5d8d5741" +SRCREV = "1741334eb0972de547d053e97d0a5b93892b070e" S = "${WORKDIR}/git" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0017-psusensor-Determine-PSU-threshold-dynamically.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0017-psusensor-Determine-PSU-threshold-dynamically.patch new file mode 100644 index 000000000..1823e96a5 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0017-psusensor-Determine-PSU-threshold-dynamically.patch @@ -0,0 +1,160 @@ +From 654fef4afba55c4f84f664b43d8a1fecc1224e7b Mon Sep 17 00:00:00 2001 +From: Vikash Chandola <vikash.chandola@intel.com> +Date: Wed, 27 Jul 2022 10:07:25 +0000 +Subject: [PATCH] psusensor: Determine PSU threshold dynamically + +PSU output current range(rated, max etc) are dependent on input +voltage. A power supply can deliver higher output on high line input +compared to low line input. Existing implementation uses static +thresholds which causes thresholds to get hit too early for high line +input. This change allows threshold to be set dynamically. + +"ThresholdLabel" and "ScaleFactor" are added in SOLUM's entity-manager +configuration file. These parameters provide pmbus register name and +scaling factor to be used for threshold calculation. psusensor fetches +"ThresholdLabel" and multiplies it with "ScaleFactor" to determine +threshold value. "ScaleFactor" allows threshold to be set in ratio to +a value. Example create a threshold that gets triggered at 0.8 times +max permissible current value. + +"ThresholdLabel" and "ScaleFactor" can be used for the cases where +threshold need to be determined on the basis on another parameter's +value. + +Tested: +Tested by running system on High line and low line input. In both +cases critical and warning thresholds were updated as per +"ThresholdLabel" and "ScaleFactor". If configuration file doesn't +contain "ThresholdLabel" and "ScaleFactor" then "Value" was used. + +Signed-off-by: Vikash Chandola <vikash.chandola@intel.com> +Change-Id: Ia588ee0971e3d4e79a9827ffd6f39398725a4273 +--- + include/Thresholds.hpp | 3 +- + src/PSUSensorMain.cpp | 2 +- + src/Thresholds.cpp | 64 +++++++++++++++++++++++++++++++++++++----- + 3 files changed, 60 insertions(+), 9 deletions(-) + +diff --git a/include/Thresholds.hpp b/include/Thresholds.hpp +index 640fdb4..7373507 100644 +--- a/include/Thresholds.hpp ++++ b/include/Thresholds.hpp +@@ -111,7 +111,8 @@ struct ThresholdTimer + bool parseThresholdsFromConfig( + const SensorData& sensorData, + std::vector<thresholds::Threshold>& thresholdVector, +- const std::string* matchLabel = nullptr, const int* sensorIndex = nullptr); ++ const std::string* matchLabel = nullptr, const int* sensorIndex = nullptr, ++ const std::string* sensorPathStr = nullptr); + + bool parseThresholdsFromAttr(std::vector<thresholds::Threshold>& thresholds, + const std::string& inputPath, +diff --git a/src/PSUSensorMain.cpp b/src/PSUSensorMain.cpp +index ae7afc3..5847863 100644 +--- a/src/PSUSensorMain.cpp ++++ b/src/PSUSensorMain.cpp +@@ -846,7 +846,7 @@ static void createSensorsCallback( + + std::vector<thresholds::Threshold> sensorThresholds; + if (!parseThresholdsFromConfig(*sensorData, sensorThresholds, +- &labelHead)) ++ &labelHead ,nullptr, &sensorPathStr)) + { + std::cerr << "error populating thresholds for " + << sensorNameSubStr << "\n"; +diff --git a/src/Thresholds.cpp b/src/Thresholds.cpp +index aef084e..cddfa2b 100644 +--- a/src/Thresholds.cpp ++++ b/src/Thresholds.cpp +@@ -56,11 +56,48 @@ std::string toBusValue(const Direction& direction) + } + } + } ++static const std::unordered_map<std::string, std::string> labelToHwmonSuffix = { ++ {"iout_oc_warn_limit", "max"}, ++}; ++ ++static std::optional<double> ++ parseThresholdFromLabel(const std::string* sensorPathStr, ++ const SensorBaseConfigMap& sensorData) ++{ ++ if (sensorPathStr == nullptr) ++ { ++ return std::nullopt; ++ } ++ auto thresholdLabelFind = sensorData.find("ThresholdLabel"); ++ auto scaleFactorFind = sensorData.find("ScaleFactor"); ++ if (thresholdLabelFind == sensorData.end() || ++ scaleFactorFind == sensorData.end()) ++ { ++ return std::nullopt; ++ } ++ auto hwmonFileSuffix = labelToHwmonSuffix.find( ++ std::visit(VariantToStringVisitor(), thresholdLabelFind->second)); ++ if (hwmonFileSuffix == labelToHwmonSuffix.end()) ++ { ++ return std::nullopt; ++ } ++ auto fileParts = splitFileName(*sensorPathStr); ++ if (!fileParts.has_value()) ++ { ++ return std::nullopt; ++ } ++ auto& [type, nr, item] = fileParts.value(); ++ auto attrPath = ++ boost::replace_all_copy(*sensorPathStr, item, hwmonFileSuffix->second); ++ return readFile(attrPath, (1.0 / std::visit(VariantToDoubleVisitor(), ++ scaleFactorFind->second))); ++} + + bool parseThresholdsFromConfig( + const SensorData& sensorData, + std::vector<thresholds::Threshold>& thresholdVector, +- const std::string* matchLabel, const int* sensorIndex) ++ const std::string* matchLabel, const int* sensorIndex, ++ const std::string* sensorPathStr) + { + for (const auto& item : sensorData) + { +@@ -110,10 +147,7 @@ bool parseThresholdsFromConfig( + + auto directionFind = item.second.find("Direction"); + auto severityFind = item.second.find("Severity"); +- auto valueFind = item.second.find("Value"); +- if (valueFind == item.second.end() || +- severityFind == item.second.end() || +- directionFind == item.second.end()) ++ if (severityFind == item.second.end() || directionFind == item.second.end()) + { + std::cerr << "Malformed threshold on configuration interface " + << item.first << "\n"; +@@ -139,8 +173,24 @@ bool parseThresholdsFromConfig( + { + direction = Direction::HIGH; + } +- double val = std::visit(VariantToDoubleVisitor(), valueFind->second); +- ++ double val = 0; ++ auto valueFind = item.second.find("Value"); ++ auto labelValueOption = parseThresholdFromLabel(sensorPathStr, item.second); ++ if (labelValueOption.has_value()) ++ { ++ val = labelValueOption.value(); ++ } ++ else if (valueFind != item.second.end()) ++ { ++ val = std::visit(VariantToDoubleVisitor(), valueFind->second); ++ } ++ else ++ { ++ std::cerr << "Failed to parse threshold value configuration for " ++ "interface " ++ << item.first << "\n"; ++ return false; ++ } + thresholdVector.emplace_back(level, direction, val, hysteresis); + } + return true; +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend index a9d4a7627..7e3356e9a 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend @@ -22,6 +22,7 @@ SRC_URI += "\ file://0014-Treat-zero-temperatures-readings-as-errors-in-IpmbSe.patch \ file://0015-Fix-for-PSU2-Power-lost-RedFish-events.patch \ file://0016-Ignore-VR-sensor-readings-if-content-is-0xFF.patch \ + file://0017-psusensor-Determine-PSU-threshold-dynamically.patch \ " DEPENDS:append = " libgpiod libmctp" diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0001-Change-to-pam_faillock-and-pam-pwquality.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0001-Change-to-pam_faillock-and-pam-pwquality.patch new file mode 100644 index 000000000..e050d9493 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager/0001-Change-to-pam_faillock-and-pam-pwquality.patch @@ -0,0 +1,492 @@ +From 0636e9177c718cd46023c454fb36825e1d000a4f Mon Sep 17 00:00:00 2001 +From: "Jason M. Bills" <jason.m.bills@intel.com> +Date: Tue, 28 Mar 2023 15:32:45 -0700 +Subject: [PATCH] Change to pam_faillock and pam pwquality + +pam_tally2 is being replaced by pam_faillock. The parameters in +common-auth have moved to faillock.conf, so this commit adds a new +method to modify paramters in a given configuration file. + +The output from the 'faillock' command differs from 'pam_tally2', so +this commit adds a new function to parse the output from 'faillock' to +determine if the user is currently locked. + +pam_cracklib is being replaced by pam_pwquality. The parameters in +common-password have moved to pwquality.conf. + +I referenced the work done by Joseph Reynolds in this commit [1] to know +what changes were required. + +[1]: https://gerrit.openbmc.org/c/openbmc/phosphor-user-manager/+/39853 + +Tested: +Confirmed that the AccountLockoutDuration and AccountLockoutThreshold +parameters under /redfish/v1/AccountService both return the correct +value from common-auth. + +Set deny to 10 and unlock_time to 30 seconds and confirmed that a user +account will correctly show as locked after 10 failed login attempts, +and that user will show as unlocked 30 seconds later. + +Used Redfish to PATCH both AccountLockoutDuration and +AccountLockoutThreshold and confirmed that the updated values are +correctly reported in Redfish and that the correct lines in +faillock.conf are modified. + +Confirmed that the MinPasswordLength parameter under +/redfish/v1/AccountService returns the correct value from +common-password. + +Set minlen to 9 and confirmed that a user password could not be set with +a length of 8. + +Used Redfish to PATCH MinPasswordLength and confirmed that the updated +value is correctly reported in Redfish and that the correct line in +pwquality.conf is modified. + +Change-Id: I0701e4148c0b8333c6b8889d4695e61ce7f5366d +Signed-off-by: Jason M. Bills <jason.m.bills@intel.com> +--- + user_mgr.cpp | 257 +++++++++++++++++++++++++++++++++++++-------------- + user_mgr.hpp | 37 ++++++++ + 2 files changed, 224 insertions(+), 70 deletions(-) + +diff --git a/user_mgr.cpp b/user_mgr.cpp +index c49fbef..68ca0ff 100644 +--- a/user_mgr.cpp ++++ b/user_mgr.cpp +@@ -51,15 +51,15 @@ static constexpr int success = 0; + static constexpr int failure = -1; + + // pam modules related +-static constexpr const char* pamTally2 = "pam_tally2.so"; +-static constexpr const char* pamCrackLib = "pam_cracklib.so"; + static constexpr const char* pamPWHistory = "pam_pwhistory.so"; + static constexpr const char* minPasswdLenProp = "minlen"; + static constexpr const char* remOldPasswdCount = "remember"; + static constexpr const char* maxFailedAttempt = "deny"; + static constexpr const char* unlockTimeout = "unlock_time"; + static constexpr const char* pamPasswdConfigFile = "/etc/pam.d/common-password"; +-static constexpr const char* pamAuthConfigFile = "/etc/pam.d/common-auth"; ++static constexpr const char* faillockConfigFile = "/etc/security/faillock.conf"; ++static constexpr const char* pwQualityConfigFile = ++ "/etc/security/pwquality.conf"; + + // Object Manager related + static constexpr const char* ldapMgrObjBasePath = +@@ -320,8 +320,8 @@ uint8_t UserMgr::minPasswordLength(uint8_t value) + { + return value; + } +- if (setPamModuleArgValue(pamCrackLib, minPasswdLenProp, +- std::to_string(value)) != success) ++ if (setPamModuleConfValue(pwQualityConfigFile, minPasswdLenProp, ++ std::to_string(value)) != success) + { + log<level::ERR>("Unable to set minPasswordLength"); + elog<InternalFailure>(); +@@ -350,8 +350,8 @@ uint16_t UserMgr::maxLoginAttemptBeforeLockout(uint16_t value) + { + return value; + } +- if (setPamModuleArgValue(pamTally2, maxFailedAttempt, +- std::to_string(value)) != success) ++ if (setPamModuleConfValue(faillockConfigFile, maxFailedAttempt, ++ std::to_string(value)) != success) + { + log<level::ERR>("Unable to set maxLoginAttemptBeforeLockout"); + elog<InternalFailure>(); +@@ -365,8 +365,8 @@ uint32_t UserMgr::accountUnlockTimeout(uint32_t value) + { + return value; + } +- if (setPamModuleArgValue(pamTally2, unlockTimeout, std::to_string(value)) != +- success) ++ if (setPamModuleConfValue(faillockConfigFile, unlockTimeout, ++ std::to_string(value)) != success) + { + log<level::ERR>("Unable to set accountUnlockTimeout"); + elog<InternalFailure>(); +@@ -378,15 +378,7 @@ int UserMgr::getPamModuleArgValue(const std::string& moduleName, + const std::string& argName, + std::string& argValue) + { +- std::string fileName; +- if (moduleName == pamTally2) +- { +- fileName = pamAuthConfigFile; +- } +- else +- { +- fileName = pamPasswdConfigFile; +- } ++ std::string fileName = pamPasswdConfigFile; + std::ifstream fileToRead(fileName, std::ios::in); + if (!fileToRead.is_open()) + { +@@ -427,19 +419,52 @@ int UserMgr::getPamModuleArgValue(const std::string& moduleName, + return failure; + } + +-int UserMgr::setPamModuleArgValue(const std::string& moduleName, +- const std::string& argName, +- const std::string& argValue) ++int UserMgr::getPamModuleConfValue(const std::string& confFile, ++ const std::string& argName, ++ std::string& argValue) + { +- std::string fileName; +- if (moduleName == pamTally2) ++ std::ifstream fileToRead(confFile, std::ios::in); ++ if (!fileToRead.is_open()) + { +- fileName = pamAuthConfigFile; ++ log<level::ERR>("Failed to open pam configuration file", ++ entry("FILE_NAME=%s", confFile.c_str())); ++ return failure; + } +- else ++ std::string line; ++ auto argSearch = argName + "="; ++ size_t startPos = 0; ++ size_t endPos = 0; ++ while (getline(fileToRead, line)) + { +- fileName = pamPasswdConfigFile; ++ // skip comments section starting with # ++ if ((startPos = line.find('#')) != std::string::npos) ++ { ++ if (startPos == 0) ++ { ++ continue; ++ } ++ // skip comments after meaningful section and process those ++ line = line.substr(0, startPos); ++ } ++ if ((startPos = line.find(argSearch)) != std::string::npos) ++ { ++ if ((endPos = line.find(' ', startPos)) == std::string::npos) ++ { ++ endPos = line.size(); ++ } ++ startPos += argSearch.size(); ++ argValue = line.substr(startPos, endPos - startPos); ++ return success; ++ } + } ++ return failure; ++} ++ ++int UserMgr::setPamModuleArgValue(const std::string& moduleName, ++ const std::string& argName, ++ const std::string& argValue) ++{ ++ std::string fileName = pamPasswdConfigFile; + std::string tmpFileName = fileName + "_tmp"; + std::ifstream fileToRead(fileName, std::ios::in); + std::ofstream fileToWrite(tmpFileName, std::ios::out); +@@ -497,6 +522,64 @@ int UserMgr::setPamModuleArgValue(const std::string& moduleName, + return failure; + } + ++int UserMgr::setPamModuleConfValue(const std::string& confFile, ++ const std::string& argName, ++ const std::string& argValue) ++{ ++ std::string tmpConfFile = confFile + "_tmp"; ++ std::ifstream fileToRead(confFile, std::ios::in); ++ std::ofstream fileToWrite(tmpConfFile, std::ios::out); ++ if (!fileToRead.is_open() || !fileToWrite.is_open()) ++ { ++ log<level::ERR>("Failed to open pam configuration /tmp file", ++ entry("FILE_NAME=%s", confFile.c_str())); ++ return failure; ++ } ++ std::string line; ++ auto argSearch = argName + "="; ++ size_t startPos = 0; ++ size_t endPos = 0; ++ bool found = false; ++ while (getline(fileToRead, line)) ++ { ++ // skip comments section starting with # ++ if ((startPos = line.find('#')) != std::string::npos) ++ { ++ if (startPos == 0) ++ { ++ fileToWrite << line << std::endl; ++ continue; ++ } ++ // skip comments after meaningful section and process those ++ line = line.substr(0, startPos); ++ } ++ if ((startPos = line.find(argSearch)) != std::string::npos) ++ { ++ if ((endPos = line.find(' ', startPos)) == std::string::npos) ++ { ++ endPos = line.size(); ++ } ++ startPos += argSearch.size(); ++ fileToWrite << line.substr(0, startPos) << argValue ++ << line.substr(endPos, line.size() - endPos) ++ << std::endl; ++ found = true; ++ continue; ++ } ++ fileToWrite << line << std::endl; ++ } ++ fileToWrite.close(); ++ fileToRead.close(); ++ if (found) ++ { ++ if (std::rename(tmpConfFile.c_str(), confFile.c_str()) == 0) ++ { ++ return success; ++ } ++ } ++ return failure; ++} ++ + void UserMgr::userEnable(const std::string& userName, bool enabled) + { + throwForUserDoesNotExist(userName); +@@ -510,51 +593,87 @@ void UserMgr::userEnable(const std::string& userName, bool enabled) + } + + /** +- * pam_tally2 app will provide the user failure count and failure status +- * in second line of output with words position [0] - user name, +- * [1] - failure count, [2] - latest timestamp, [3] - failure timestamp +- * [4] - failure app ++ * faillock app will provide the user failed login list with when the attempt ++ * was made, the type, the source, and if it's valid. ++ * ++ * Valid in this case means that the attempt was made within the fail_interval ++ * time. So, we can check this list for the number of valid entries (lines ++ * ending with 'V') compared to the maximum allowed to determine if the user is ++ * locked out. ++ * ++ * This data is only refreshed when an attempt is made, so if the user appears ++ * to be locked out, we must also check if the most recent attempt was older ++ * than the unlock_time to know if the user has since been unlocked. + **/ +- +-static constexpr size_t t2UserIdx = 0; +-static constexpr size_t t2FailCntIdx = 1; +-static constexpr size_t t2OutputIndex = 1; +- +-bool UserMgr::userLockedForFailedAttempt(const std::string& userName) ++bool UserMgr::parseFaillockForLockout( ++ const std::vector<std::string>& faillockOutput) + { +- // All user management lock has to be based on /etc/shadow +- // TODO phosphor-user-manager#10 phosphor::user::shadow::Lock lock{}; +- std::vector<std::string> output; +- +- output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str()); ++ uint16_t failAttempts = 0; ++ time_t lastFailedAttempt{}; ++ for (const std::string& line : faillockOutput) ++ { ++ if (!boost::ends_with(line, "V")) ++ { ++ continue; ++ } + +- std::vector<std::string> splitWords; +- boost::algorithm::split(splitWords, output[t2OutputIndex], +- boost::algorithm::is_any_of("\t "), +- boost::token_compress_on); ++ // Count this failed attempt ++ failAttempts++; + +- try +- { +- unsigned long tmp = std::stoul(splitWords[t2FailCntIdx], nullptr); +- uint16_t value16 = 0; +- if (tmp > std::numeric_limits<decltype(value16)>::max()) ++ // Update the last attempt time ++ // First get the "when" which is the first two words (date and time) ++ size_t pos = line.find(" "); ++ if (pos == std::string::npos) ++ { ++ continue; ++ } ++ pos = line.find(" ", pos + 1); ++ if (pos == std::string::npos) + { +- throw std::out_of_range("Out of range"); ++ continue; + } +- value16 = static_cast<decltype(value16)>(tmp); +- if (AccountPolicyIface::maxLoginAttemptBeforeLockout() != 0 && +- value16 >= AccountPolicyIface::maxLoginAttemptBeforeLockout()) ++ std::string failDateTime = line.substr(0, pos); ++ ++ // NOTE: Cannot use std::get_time() here as the implementation of %y in ++ // libstdc++ does not match POSIX strptime() before gcc 12.1.0 ++ // https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=a8d3c98746098e2784be7144c1ccc9fcc34a0888 ++ std::tm tmStruct = {}; ++ if (!strptime(failDateTime.c_str(), "%F %T", &tmStruct)) + { +- return true; // User account is locked out ++ // log<level::ERR>("Failed to parse latest failure date/time"); ++ // elog<InternalFailure>(); + } +- return false; // User account is un-locked ++ ++ time_t failTimestamp = std::mktime(&tmStruct); ++ lastFailedAttempt = std::max(failTimestamp, lastFailedAttempt); ++ } ++ ++ if (failAttempts < AccountPolicyIface::maxLoginAttemptBeforeLockout()) ++ { ++ return false; + } +- catch (const std::exception& e) ++ ++ if (lastFailedAttempt + ++ static_cast<time_t>(AccountPolicyIface::accountUnlockTimeout()) <= ++ std::time(NULL)) + { +- log<level::ERR>("Exception for userLockedForFailedAttempt", +- entry("WHAT=%s", e.what())); +- throw; ++ return false; + } ++ ++ return true; ++} ++ ++bool UserMgr::userLockedForFailedAttempt(const std::string& userName) ++{ ++ // All user management lock has to be based on /etc/shadow ++ // TODO phosphor-user-manager#10 phosphor::user::shadow::Lock lock{}; ++ ++ std::vector<std::string> output; ++ ++ output = ++ executeCmd("/usr/sbin/faillock", "--user", userName.c_str(), "--reset"); ++ ++ return parseFaillockForLockout(output); + } + + bool UserMgr::userLockedForFailedAttempt(const std::string& userName, +@@ -567,12 +686,8 @@ bool UserMgr::userLockedForFailedAttempt(const std::string& userName, + { + return userLockedForFailedAttempt(userName); + } +- output = executeCmd("/usr/sbin/pam_tally2", "-u", userName.c_str(), "-r"); +- +- std::vector<std::string> splitWords; +- boost::algorithm::split(splitWords, output[t2OutputIndex], +- boost::algorithm::is_any_of("\t "), +- boost::token_compress_on); ++ output = ++ executeCmd("/usr/sbin/faillock", "--user", userName.c_str(), "--reset"); + + return userLockedForFailedAttempt(userName); + } +@@ -940,8 +1055,8 @@ UserMgr::UserMgr(sdbusplus::bus::bus& bus, const char* path, + std::string valueStr; + auto value = minPasswdLength; + unsigned long tmp = 0; +- if (getPamModuleArgValue(pamCrackLib, minPasswdLenProp, valueStr) != +- success) ++ if (getPamModuleConfValue(pwQualityConfigFile, minPasswdLenProp, ++ valueStr) != success) + { + AccountPolicyIface::minPasswordLength(minPasswdLength); + } +@@ -991,7 +1106,8 @@ UserMgr::UserMgr(sdbusplus::bus::bus& bus, const char* path, + AccountPolicyIface::rememberOldPasswordTimes(value); + } + valueStr.clear(); +- if (getPamModuleArgValue(pamTally2, maxFailedAttempt, valueStr) != success) ++ if (getPamModuleConfValue(faillockConfigFile, maxFailedAttempt, valueStr) != ++ success) + { + AccountPolicyIface::maxLoginAttemptBeforeLockout(0); + } +@@ -1016,7 +1132,8 @@ UserMgr::UserMgr(sdbusplus::bus::bus& bus, const char* path, + AccountPolicyIface::maxLoginAttemptBeforeLockout(value16); + } + valueStr.clear(); +- if (getPamModuleArgValue(pamTally2, unlockTimeout, valueStr) != success) ++ if (getPamModuleConfValue(faillockConfigFile, unlockTimeout, valueStr) != ++ success) + { + AccountPolicyIface::accountUnlockTimeout(0); + } +diff --git a/user_mgr.hpp b/user_mgr.hpp +index 5d5ca99..92a265b 100644 +--- a/user_mgr.hpp ++++ b/user_mgr.hpp +@@ -155,6 +155,14 @@ class UserMgr : public Ifaces + */ + uint32_t accountUnlockTimeout(uint32_t val) override; + ++ /** @brief parses the faillock output for locked user status ++ * ++ * @param[in] - output from faillock for the user ++ * @return - true / false indicating user locked / un-locked ++ **/ ++ bool ++ parseFaillockForLockout(const std::vector<std::string>& faillockOutput); ++ + /** @brief lists user locked state for failed attempt + * + * @param[in] - user name +@@ -311,6 +319,20 @@ class UserMgr : public Ifaces + int getPamModuleArgValue(const std::string& moduleName, + const std::string& argName, std::string& argValue); + ++ /** @brief get pam argument value ++ * method to get argument value from pam configuration ++ * ++ * @param[in] confFile - path of the module config file from where arg has ++ * to be read ++ * @param[in] argName - argument name ++ * @param[out] argValue - argument value ++ * ++ * @return 0 - success state of the function ++ */ ++ int getPamModuleConfValue(const std::string& confFile, ++ const std::string& argName, ++ std::string& argValue); ++ + /** @brief set pam argument value + * method to set argument value in pam configuration + * +@@ -325,6 +347,20 @@ class UserMgr : public Ifaces + const std::string& argName, + const std::string& argValue); + ++ /** @brief set pam argument value ++ * method to set argument value in pam configuration ++ * ++ * @param[in] confFile - path of the module config file in which argument ++ * value has to be set ++ * @param[in] argName - argument name ++ * @param[out] argValue - argument value ++ * ++ * @return 0 - success state of the function ++ */ ++ int setPamModuleConfValue(const std::string& confFile, ++ const std::string& argName, ++ const std::string& argValue); ++ + /** @brief get service name + * method to get dbus service name + * +@@ -351,6 +387,7 @@ class UserMgr : public Ifaces + virtual DbusUserObj getPrivilegeMapperObject(void); + + friend class TestUserMgr; ++ + }; + + } // namespace user +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend index 0bf528eb4..88a2b0f2d 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/users/phosphor-user-manager_%.bbappend @@ -6,6 +6,7 @@ SRCREV = "b01e2fe760eb04ae9d0d13716a127056949e2601" EXTRA_OECONF += "${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'allow-root-login' ], '', '--disable-root_user_mgmt', d)}" SRC_URI += " \ + file://0001-Change-to-pam_faillock-and-pam-pwquality.patch \ file://0005-Added-suport-for-multiple-user-manager-services.patch \ file://0006-Use-groupmems-instead-of-getgrnam_r-due-to-overlay.patch \ " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue/0001-Old-password-input-in-change-password-screen.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue/0001-Old-password-input-in-change-password-screen.patch new file mode 100644 index 000000000..313ba9387 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue/0001-Old-password-input-in-change-password-screen.patch @@ -0,0 +1,135 @@ +From 9da7bafdcee1bd022b7e47eecf704eb799b389e8 Mon Sep 17 00:00:00 2001 +From: Yaswanth Reddy M <yaswanthx.reddy.munukuru@intel.com> +Date: Wed, 17 May 2023 10:47:56 +0000 +Subject: [PATCH] Old password input in change password screen + +When the user changed their password in profile settings, to prevent +XSS attacks, I added the current password input field to authenticate +the user. + +Once the authentication had success with the current password, then +allowing the update was possible. After the password is changed +successfully, all the sessions of the user who changed the password +will be disconnected, including the current session. and the current +session will navigate to the login page. + +Signed-off-by: Yaswanth Reddy M <yaswanthx.reddy.munukuru@intel.com> +--- + src/locales/en-US.json | 4 +- + src/views/ProfileSettings/ProfileSettings.vue | 54 +++++++++++++++++-- + 2 files changed, 53 insertions(+), 5 deletions(-) + +diff --git a/src/locales/en-US.json b/src/locales/en-US.json +index 637f052..8d98abb 100644 +--- a/src/locales/en-US.json ++++ b/src/locales/en-US.json +@@ -617,6 +617,7 @@ + "confirmPassword": "Confirm new password", + "defaultUTC": "Default (UTC)", + "newPassword": "New password", ++ "currentPassword": "Current password", + "newPassLabelTextInfo": "Password must be between %{min} - %{max} characters", + "passwordsDoNotMatch": "Passwords do not match", + "profileInfoTitle": "Profile information", +@@ -625,7 +626,8 @@ + "timezoneDisplayDesc": "Select how time is displayed throughout the application", + "username": "Username", + "toast": { +- "successSaveSettings": "Successfully saved account settings." ++ "successSaveSettings": "Successfully saved account settings.", ++ "wrongCredentials": "Wrong credentials" + } + }, + "pageNetwork": { +diff --git a/src/views/ProfileSettings/ProfileSettings.vue b/src/views/ProfileSettings/ProfileSettings.vue +index 35fc800..330fd4a 100644 +--- a/src/views/ProfileSettings/ProfileSettings.vue ++++ b/src/views/ProfileSettings/ProfileSettings.vue +@@ -23,6 +23,21 @@ + <page-section + :section-title="$t('pageProfileSettings.changePassword')" + > ++ <b-form-group ++ id="input-group-0" ++ :label="$t('pageProfileSettings.currentPassword')" ++ label-for="input-0" ++ > ++ <input-password-toggle> ++ <b-form-input ++ id="old-password" ++ v-model="form.currentPassword" ++ type="password" ++ data-test-id="profileSettings-input-ocurrentPassword" ++ class="form-control-with-button" ++ /> ++ </input-password-toggle> ++ </b-form-group> + <b-form-group + id="input-group-1" + :label="$t('pageProfileSettings.newPassword')" +@@ -151,6 +166,7 @@ export default { + form: { + newPassword: '', + confirmPassword: '', ++ currentPassword: '', + isUtcDisplay: this.$store.getters['global/isUtcDisplay'], + }, + }; +@@ -198,9 +214,12 @@ export default { + this.$store + .dispatch('userManagement/updateUser', userData) + .then((message) => { +- (this.form.newPassword = ''), (this.form.confirmPassword = ''); ++ (this.form.newPassword = ''), ++ (this.form.confirmPassword = ''), ++ (this.form.currentPassword = ''); + this.$v.$reset(); + this.successToast(message); ++ this.$store.dispatch('authentication/logout'); + }) + .catch(({ message }) => this.errorToast(message)); + }, +@@ -212,10 +231,37 @@ export default { + ); + }, + submitForm() { +- if (this.form.confirmPassword || this.form.newPassword) { +- this.saveNewPasswordInputData(); ++ if ( ++ this.form.confirmPassword && ++ this.form.newPassword && ++ this.form.currentPassword ++ ) { ++ this.confirmAuthenticate(); + } +- this.saveTimeZonePrefrenceData(); ++ if ( ++ this.$store.getters['global/isUtcDisplay'] != this.form.isUtcDisplay ++ ) { ++ this.saveTimeZonePrefrenceData(); ++ } ++ }, ++ confirmAuthenticate() { ++ this.$v.form.newPassword.$touch(); ++ if (this.$v.$invalid) return; ++ ++ const username = this.username; ++ const password = this.form.currentPassword; ++ ++ this.$store ++ .dispatch('authentication/login', { username, password }) ++ .then(() => { ++ this.saveNewPasswordInputData(); ++ }) ++ .catch(() => { ++ this.$v.$reset(); ++ this.errorToast( ++ this.$t('pageProfileSettings.toast.wrongCredentials') ++ ); ++ }); + }, + }, + }; +-- +2.25.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend index bdd6a3bad..412e88501 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend @@ -6,6 +6,7 @@ FILESEXTRAPATHS:append := "${THISDIR}/${PN}:" SRC_URI += " \ file://login-company-logo.svg \ file://logo-header.svg \ + file://0001-Old-password-input-in-change-password-screen.patch \ " do_compile:prepend() { diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/0001-replace-krb5-config-with-pkg-config.patch b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/0001-replace-krb5-config-with-pkg-config.patch deleted file mode 100644 index a7db1b3c9..000000000 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/0001-replace-krb5-config-with-pkg-config.patch +++ /dev/null @@ -1,44 +0,0 @@ -From ed70f0623708b8a6c1f58a5d243d87c5ff45b24d Mon Sep 17 00:00:00 2001 -From: Roy Li <rongqing.li@windriver.com> -Date: Tue, 26 Apr 2016 13:13:01 +0800 -Subject: [PATCH] replace krb5-config with pkg-config - -Upstream-Status: Pending - -Signed-off-by: Roy Li <rongqing.li@windriver.com> - ---- - configure.ac | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/configure.ac b/configure.ac -index 5569a26..56b0380 100755 ---- a/configure.ac -+++ b/configure.ac -@@ -1290,7 +1290,7 @@ AC_ARG_WITH(gssapi, - fi - ]) - --: ${KRB5CONFIG:="$GSSAPI_ROOT/bin/krb5-config"} -+KRB5CONFIG=`which pkg-config` - - save_CPPFLAGS="$CPPFLAGS" - AC_MSG_CHECKING([if GSS-API support is requested]) -@@ -1301,7 +1301,7 @@ if test x"$want_gss" = xyes; then - if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then - GSSAPI_INCS=`$GSSAPI_ROOT/bin/$host_alias-krb5-config --cflags gssapi` - elif test -f "$KRB5CONFIG"; then -- GSSAPI_INCS=`$KRB5CONFIG --cflags gssapi` -+ GSSAPI_INCS=`$KRB5CONFIG --cflags mit-krb5-gssapi` - elif test "$GSSAPI_ROOT" != "yes"; then - GSSAPI_INCS="-I$GSSAPI_ROOT/include" - fi -@@ -1394,7 +1394,7 @@ if test x"$want_gss" = xyes; then - elif test -f "$KRB5CONFIG"; then - dnl krb5-config doesn't have --libs-only-L or similar, put everything - dnl into LIBS -- gss_libs=`$KRB5CONFIG --libs gssapi` -+ gss_libs=`$KRB5CONFIG --libs mit-krb5-gssapi` - LIBS="$gss_libs $LIBS" - else - case $host in diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32205-cookie-apply-limits.patch b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32205-cookie-apply-limits.patch deleted file mode 100644 index dc7b59f7f..000000000 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32205-cookie-apply-limits.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 48d7064a49148f03942380967da739dcde1cdc24 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg <daniel@haxx.se> -Date: Sun, 26 Jun 2022 11:00:48 +0200 -Subject: [PATCH] cookie: apply limits - -- Send no more than 150 cookies per request -- Cap the max length used for a cookie: header to 8K -- Cap the max number of received Set-Cookie: headers to 50 - -Bug: https://curl.se/docs/CVE-2022-32205.html -CVE-2022-32205 -Reported-by: Harry Sintonen -Closes #9048 ---- - lib/cookie.c | 14 ++++++++++++-- - lib/cookie.h | 21 +++++++++++++++++++-- - lib/http.c | 13 +++++++++++-- - lib/urldata.h | 1 + - 4 files changed, 43 insertions(+), 6 deletions(-) - -diff --git a/lib/cookie.c b/lib/cookie.c -index a308346a777bc..a1ab89532033b 100644 ---- a/lib/cookie.c -+++ b/lib/cookie.c -@@ -482,6 +482,10 @@ Curl_cookie_add(struct Curl_easy *data, - (void)data; - #endif - -+ DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */ -+ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT) -+ return NULL; -+ - /* First, alloc and init a new struct for it */ - co = calloc(1, sizeof(struct Cookie)); - if(!co) -@@ -821,7 +825,7 @@ Curl_cookie_add(struct Curl_easy *data, - freecookie(co); - return NULL; - } -- -+ data->req.setcookies++; - } - else { - /* -@@ -1375,7 +1379,8 @@ static struct Cookie *dup_cookie(struct Cookie *src) - * - * It shall only return cookies that haven't expired. - */ --struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, -+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, -+ struct CookieInfo *c, - const char *host, const char *path, - bool secure) - { -@@ -1430,6 +1435,11 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, - mainco = newco; - - matches++; -+ if(matches >= MAX_COOKIE_SEND_AMOUNT) { -+ infof(data, "Included max number of cookies (%u) in request!", -+ matches); -+ break; -+ } - } - else - goto fail; -diff --git a/lib/cookie.h b/lib/cookie.h -index 453dfced8a342..abc0a2e8a01ad 100644 ---- a/lib/cookie.h -+++ b/lib/cookie.h -@@ -83,10 +83,26 @@ struct CookieInfo { - */ - #define MAX_COOKIE_LINE 5000 - --/* This is the maximum length of a cookie name or content we deal with: */ -+/* Maximum length of an incoming cookie name or content we deal with. Longer -+ cookies are ignored. */ - #define MAX_NAME 4096 - #define MAX_NAME_TXT "4095" - -+/* Maximum size for an outgoing cookie line libcurl will use in an http -+ request. This is the default maximum length used in some versions of Apache -+ httpd. */ -+#define MAX_COOKIE_HEADER_LEN 8190 -+ -+/* Maximum number of cookies libcurl will send in a single request, even if -+ there might be more cookies that match. One reason to cap the number is to -+ keep the maximum HTTP request within the maximum allowed size. */ -+#define MAX_COOKIE_SEND_AMOUNT 150 -+ -+/* Maximum number of Set-Cookie: lines accepted in a single response. If more -+ such header lines are received, they are ignored. This value must be less -+ than 256 since an unsigned char is used to count. */ -+#define MAX_SET_COOKIE_AMOUNT 50 -+ - struct Curl_easy; - /* - * Add a cookie to the internal list of cookies. The domain and path arguments -@@ -99,7 +115,8 @@ struct Cookie *Curl_cookie_add(struct Curl_easy *data, - const char *domain, const char *path, - bool secure); - --struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, const char *host, -+struct Cookie *Curl_cookie_getlist(struct Curl_easy *data, -+ struct CookieInfo *c, const char *host, - const char *path, bool secure); - void Curl_cookie_freelist(struct Cookie *cookies); - void Curl_cookie_clearall(struct CookieInfo *cookies); -diff --git a/lib/http.c b/lib/http.c -index 5284475ba92c4..258722a602e40 100644 ---- a/lib/http.c -+++ b/lib/http.c -@@ -2711,12 +2711,14 @@ CURLcode Curl_http_bodysend(struct Curl_easy *data, struct connectdata *conn, - } - - #if !defined(CURL_DISABLE_COOKIES) -+ - CURLcode Curl_http_cookies(struct Curl_easy *data, - struct connectdata *conn, - struct dynbuf *r) - { - CURLcode result = CURLE_OK; - char *addcookies = NULL; -+ bool linecap = FALSE; - if(data->set.str[STRING_COOKIE] && - !Curl_checkheaders(data, STRCONST("Cookie"))) - addcookies = data->set.str[STRING_COOKIE]; -@@ -2734,7 +2736,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, - !strcmp(host, "127.0.0.1") || - !strcmp(host, "[::1]") ? TRUE : FALSE; - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); -- co = Curl_cookie_getlist(data->cookies, host, data->state.up.path, -+ co = Curl_cookie_getlist(data, data->cookies, host, data->state.up.path, - secure_context); - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } -@@ -2748,6 +2750,13 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, - if(result) - break; - } -+ if((Curl_dyn_len(r) + strlen(co->name) + strlen(co->value) + 1) >= -+ MAX_COOKIE_HEADER_LEN) { -+ infof(data, "Restricted outgoing cookies due to header size, " -+ "'%s' not sent", co->name); -+ linecap = TRUE; -+ break; -+ } - result = Curl_dyn_addf(r, "%s%s=%s", count?"; ":"", - co->name, co->value); - if(result) -@@ -2758,7 +2767,7 @@ CURLcode Curl_http_cookies(struct Curl_easy *data, - } - Curl_cookie_freelist(store); - } -- if(addcookies && !result) { -+ if(addcookies && !result && !linecap) { - if(!count) - result = Curl_dyn_addn(r, STRCONST("Cookie: ")); - if(!result) { -diff --git a/lib/urldata.h b/lib/urldata.h -index 17fe25720be33..bcb4d460c2fe6 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -698,6 +698,7 @@ struct SingleRequest { - #ifndef CURL_DISABLE_DOH - struct dohdata *doh; /* DoH specific data for this request */ - #endif -+ unsigned char setcookies; - BIT(header); /* incoming data has HTTP header */ - BIT(content_range); /* set TRUE if Content-Range: was found */ - BIT(upload_done); /* set to TRUE when doing chunked transfer-encoding diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32206-return-error-on-too-many-compression-steps.patch b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32206-return-error-on-too-many-compression-steps.patch deleted file mode 100644 index bdf3ba35e..000000000 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32206-return-error-on-too-many-compression-steps.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 3a09fbb7f264c67c438d01a30669ce325aa508e2 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg <daniel@haxx.se> -Date: Mon, 16 May 2022 16:28:13 +0200 -Subject: [PATCH] content_encoding: return error on too many compression steps - -The max allowed steps is arbitrarily set to 5. - -Bug: https://curl.se/docs/CVE-2022-32206.html -CVE-2022-32206 -Reported-by: Harry Sintonen -Closes #9049 ---- - lib/content_encoding.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/lib/content_encoding.c b/lib/content_encoding.c -index c5591ca48ac78..95ba48a2dd563 100644 ---- a/lib/content_encoding.c -+++ b/lib/content_encoding.c -@@ -1028,12 +1028,16 @@ static const struct content_encoding *find_encoding(const char *name, - return NULL; - } - -+/* allow no more than 5 "chained" compression steps */ -+#define MAX_ENCODE_STACK 5 -+ - /* Set-up the unencoding stack from the Content-Encoding header value. - * See RFC 7231 section 3.1.2.2. */ - CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - const char *enclist, int maybechunked) - { - struct SingleRequest *k = &data->req; -+ int counter = 0; - - do { - const char *name; -@@ -1068,6 +1072,11 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, - if(!encoding) - encoding = &error_encoding; /* Defer error at stack use. */ - -+ if(++counter >= MAX_ENCODE_STACK) { -+ failf(data, "Reject response due to %u content encodings", -+ counter); -+ return CURLE_BAD_CONTENT_ENCODING; -+ } - /* Stack the unencoding stage. */ - writer = new_unencoding_writer(data, encoding, k->writer_stack); - if(!writer) diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32207-fopen-add-Curl_fopen-for-better-overwriting-of-fi.patch b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32207-fopen-add-Curl_fopen-for-better-overwriting-of-fi.patch deleted file mode 100644 index 9b4c128d9..000000000 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32207-fopen-add-Curl_fopen-for-better-overwriting-of-fi.patch +++ /dev/null @@ -1,280 +0,0 @@ -From 20f9dd6bae50b7223171b17ba7798946e74f877f Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg <daniel@haxx.se> -Date: Wed, 25 May 2022 10:09:53 +0200 -Subject: [PATCH] fopen: add Curl_fopen() for better overwriting of files - -Bug: https://curl.se/docs/CVE-2022-32207.html -CVE-2022-32207 -Reported-by: Harry Sintonen -Closes #9050 ---- - CMakeLists.txt | 1 + - configure.ac | 1 + - lib/Makefile.inc | 2 + - lib/cookie.c | 19 ++----- - lib/curl_config.h.cmake | 3 ++ - lib/fopen.c | 113 ++++++++++++++++++++++++++++++++++++++++ - lib/fopen.h | 30 +++++++++++ - 7 files changed, 154 insertions(+), 15 deletions(-) - create mode 100644 lib/fopen.c - create mode 100644 lib/fopen.h - -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 45d763d5a9c1d..ad20777f3d688 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -1067,6 +1067,7 @@ elseif(HAVE_LIBSOCKET) - set(CMAKE_REQUIRED_LIBRARIES socket) - endif() - -+check_symbol_exists(fchmod "${CURL_INCLUDES}" HAVE_FCHMOD) - check_symbol_exists(basename "${CURL_INCLUDES}" HAVE_BASENAME) - check_symbol_exists(socket "${CURL_INCLUDES}" HAVE_SOCKET) - check_symbol_exists(select "${CURL_INCLUDES}" HAVE_SELECT) -diff --git a/configure.ac b/configure.ac -index b0245b99a669f..de2dee5a484ed 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -3438,6 +3438,7 @@ AC_CHECK_DECLS([getpwuid_r], [], [AC_DEFINE(HAVE_DECL_GETPWUID_R_MISSING, 1, "Se - - - AC_CHECK_FUNCS([fnmatch \ -+ fchmod \ - geteuid \ - getpass_r \ - getppid \ -diff --git a/lib/Makefile.inc b/lib/Makefile.inc -index 533e16df97020..9bd8e324bd1c1 100644 ---- a/lib/Makefile.inc -+++ b/lib/Makefile.inc -@@ -137,6 +137,7 @@ LIB_CFILES = \ - escape.c \ - file.c \ - fileinfo.c \ -+ fopen.c \ - formdata.c \ - ftp.c \ - ftplistparser.c \ -@@ -270,6 +271,7 @@ LIB_HFILES = \ - escape.h \ - file.h \ - fileinfo.h \ -+ fopen.h \ - formdata.h \ - ftp.h \ - ftplistparser.h \ -diff --git a/lib/cookie.c b/lib/cookie.c -index a1ab89532033b..cb57b86387191 100644 ---- a/lib/cookie.c -+++ b/lib/cookie.c -@@ -99,8 +99,8 @@ Example set of cookies: - #include "curl_get_line.h" - #include "curl_memrchr.h" - #include "parsedate.h" --#include "rand.h" - #include "rename.h" -+#include "fopen.h" - - /* The last 3 #include files should be in this order */ - #include "curl_printf.h" -@@ -1641,20 +1641,9 @@ static CURLcode cookie_output(struct Curl_easy *data, - use_stdout = TRUE; - } - else { -- unsigned char randsuffix[9]; -- -- if(Curl_rand_hex(data, randsuffix, sizeof(randsuffix))) -- return 2; -- -- tempstore = aprintf("%s.%s.tmp", filename, randsuffix); -- if(!tempstore) -- return CURLE_OUT_OF_MEMORY; -- -- out = fopen(tempstore, FOPEN_WRITETEXT); -- if(!out) { -- error = CURLE_WRITE_ERROR; -+ error = Curl_fopen(data, filename, &out, &tempstore); -+ if(error) - goto error; -- } - } - - fputs("# Netscape HTTP Cookie File\n" -@@ -1701,7 +1690,7 @@ static CURLcode cookie_output(struct Curl_easy *data, - if(!use_stdout) { - fclose(out); - out = NULL; -- if(Curl_rename(tempstore, filename)) { -+ if(tempstore && Curl_rename(tempstore, filename)) { - unlink(tempstore); - error = CURLE_WRITE_ERROR; - goto error; -diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake -index cd4b568d89948..eb2c62b971453 100644 ---- a/lib/curl_config.h.cmake -+++ b/lib/curl_config.h.cmake -@@ -159,6 +159,9 @@ - /* Define to 1 if you have the <assert.h> header file. */ - #cmakedefine HAVE_ASSERT_H 1 - -+/* Define to 1 if you have the `fchmod' function. */ -+#cmakedefine HAVE_FCHMOD 1 -+ - /* Define to 1 if you have the `basename' function. */ - #cmakedefine HAVE_BASENAME 1 - -diff --git a/lib/fopen.c b/lib/fopen.c -new file mode 100644 -index 0000000000000..ad3691ba9d158 ---- /dev/null -+++ b/lib/fopen.c -@@ -0,0 +1,113 @@ -+/*************************************************************************** -+ * _ _ ____ _ -+ * Project ___| | | | _ \| | -+ * / __| | | | |_) | | -+ * | (__| |_| | _ <| |___ -+ * \___|\___/|_| \_\_____| -+ * -+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. -+ * -+ * This software is licensed as described in the file COPYING, which -+ * you should have received as part of this distribution. The terms -+ * are also available at https://curl.se/docs/copyright.html. -+ * -+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell -+ * copies of the Software, and permit persons to whom the Software is -+ * furnished to do so, under the terms of the COPYING file. -+ * -+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -+ * KIND, either express or implied. -+ * -+ * SPDX-License-Identifier: curl -+ * -+ ***************************************************************************/ -+ -+#include "curl_setup.h" -+ -+#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \ -+ !defined(CURL_DISABLE_HSTS) -+ -+#ifdef HAVE_FCNTL_H -+#include <fcntl.h> -+#endif -+ -+#include "urldata.h" -+#include "rand.h" -+#include "fopen.h" -+/* The last 3 #include files should be in this order */ -+#include "curl_printf.h" -+#include "curl_memory.h" -+#include "memdebug.h" -+ -+/* -+ * Curl_fopen() opens a file for writing with a temp name, to be renamed -+ * to the final name when completed. If there is an existing file using this -+ * name at the time of the open, this function will clone the mode from that -+ * file. if 'tempname' is non-NULL, it needs a rename after the file is -+ * written. -+ */ -+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, -+ FILE **fh, char **tempname) -+{ -+ CURLcode result = CURLE_WRITE_ERROR; -+ unsigned char randsuffix[9]; -+ char *tempstore = NULL; -+ struct_stat sb; -+ int fd = -1; -+ *tempname = NULL; -+ -+ if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) { -+ /* a non-regular file, fallback to direct fopen() */ -+ *fh = fopen(filename, FOPEN_WRITETEXT); -+ if(*fh) -+ return CURLE_OK; -+ goto fail; -+ } -+ -+ result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix)); -+ if(result) -+ goto fail; -+ -+ tempstore = aprintf("%s.%s.tmp", filename, randsuffix); -+ if(!tempstore) { -+ result = CURLE_OUT_OF_MEMORY; -+ goto fail; -+ } -+ -+ result = CURLE_WRITE_ERROR; -+ fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600); -+ if(fd == -1) -+ goto fail; -+ -+#ifdef HAVE_FCHMOD -+ { -+ struct_stat nsb; -+ if((fstat(fd, &nsb) != -1) && -+ (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) { -+ /* if the user and group are the same, clone the original mode */ -+ if(fchmod(fd, sb.st_mode) == -1) -+ goto fail; -+ } -+ } -+#endif -+ -+ *fh = fdopen(fd, FOPEN_WRITETEXT); -+ if(!*fh) -+ goto fail; -+ -+ *tempname = tempstore; -+ return CURLE_OK; -+ -+fail: -+ if(fd != -1) { -+ close(fd); -+ unlink(tempstore); -+ } -+ -+ free(tempstore); -+ -+ *tempname = NULL; -+ return result; -+} -+ -+#endif /* ! disabled */ -diff --git a/lib/fopen.h b/lib/fopen.h -new file mode 100644 -index 0000000000000..289e55f2afd24 ---- /dev/null -+++ b/lib/fopen.h -@@ -0,0 +1,30 @@ -+#ifndef HEADER_CURL_FOPEN_H -+#define HEADER_CURL_FOPEN_H -+/*************************************************************************** -+ * _ _ ____ _ -+ * Project ___| | | | _ \| | -+ * / __| | | | |_) | | -+ * | (__| |_| | _ <| |___ -+ * \___|\___/|_| \_\_____| -+ * -+ * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al. -+ * -+ * This software is licensed as described in the file COPYING, which -+ * you should have received as part of this distribution. The terms -+ * are also available at https://curl.se/docs/copyright.html. -+ * -+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell -+ * copies of the Software, and permit persons to whom the Software is -+ * furnished to do so, under the terms of the COPYING file. -+ * -+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -+ * KIND, either express or implied. -+ * -+ * SPDX-License-Identifier: curl -+ * -+ ***************************************************************************/ -+ -+CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, -+ FILE **fh, char **tempname); -+ -+#endif diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32208-krb5-return-error-properly-on-decode-errors.patch b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32208-krb5-return-error-properly-on-decode-errors.patch deleted file mode 100644 index be9f52d86..000000000 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/CVE-2022-32208-krb5-return-error-properly-on-decode-errors.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 6ecdf5136b52af747e7bda08db9a748256b1cd09 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg <daniel@haxx.se> -Date: Thu, 9 Jun 2022 09:27:24 +0200 -Subject: [PATCH] krb5: return error properly on decode errors - -Bug: https://curl.se/docs/CVE-2022-32208.html -CVE-2022-32208 -Reported-by: Harry Sintonen -Closes #9051 ---- - lib/krb5.c | 18 +++++++++++------- - 1 file changed, 11 insertions(+), 7 deletions(-) - -diff --git a/lib/krb5.c b/lib/krb5.c -index e289595c9e1dd..517491c4658bf 100644 ---- a/lib/krb5.c -+++ b/lib/krb5.c -@@ -142,11 +142,8 @@ krb5_decode(void *app_data, void *buf, int len, - enc.value = buf; - enc.length = len; - maj = gss_unwrap(&min, *context, &enc, &dec, NULL, NULL); -- if(maj != GSS_S_COMPLETE) { -- if(len >= 4) -- strcpy(buf, "599 "); -+ if(maj != GSS_S_COMPLETE) - return -1; -- } - - memcpy(buf, dec.value, dec.length); - len = curlx_uztosi(dec.length); -@@ -508,6 +505,7 @@ static CURLcode read_data(struct connectdata *conn, - { - int len; - CURLcode result; -+ int nread; - - result = socket_read(fd, &len, sizeof(len)); - if(result) -@@ -516,7 +514,10 @@ static CURLcode read_data(struct connectdata *conn, - if(len) { - /* only realloc if there was a length */ - len = ntohl(len); -- buf->data = Curl_saferealloc(buf->data, len); -+ if(len > CURL_MAX_INPUT_LENGTH) -+ len = 0; -+ else -+ buf->data = Curl_saferealloc(buf->data, len); - } - if(!len || !buf->data) - return CURLE_OUT_OF_MEMORY; -@@ -524,8 +525,11 @@ static CURLcode read_data(struct connectdata *conn, - result = socket_read(fd, buf->data, len); - if(result) - return result; -- buf->size = conn->mech->decode(conn->app_data, buf->data, len, -- conn->data_prot, conn); -+ nread = conn->mech->decode(conn->app_data, buf->data, len, -+ conn->data_prot, conn); -+ if(nread < 0) -+ return CURLE_RECV_ERROR; -+ buf->size = (size_t)nread; - buf->index = 0; - return CURLE_OK; - } diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/disable-tests b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/disable-tests new file mode 100644 index 000000000..92056bd8c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/disable-tests @@ -0,0 +1,28 @@ +# These CRL test (alt-avc) are failing +356 +412 +413 +# These CRL tests are scanning docs +971 +1119 +1132 +1135 +# These CRL tests are scnning headers +1167 +# These CRL tests are scanning man pages +1139 +1140 +1173 +1177 +# This CRL test is looking for m4 files +1165 +# This CRL test is looking for src files +1185 +# These CRL tests need --libcurl option to be enabled +1400 +1401 +1402 +1403 +1404 +1405 +1465 diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl/run-ptest b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/run-ptest new file mode 100644 index 000000000..614e82292 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/curl/curl/run-ptest @@ -0,0 +1,6 @@ +#!/bin/sh +cd tests +./runtests.pl -a -n -s | sed \ + -e 's|\([^ ]* *\) \([^ ]* *\)...OK|PASS: \1 \2|' \ + -e 's|\([^ ]* *\) \([^ ]* *\)...FAILED|FAIL: \1 \2|' \ + -e 's/Warning: test[0-9]\+ not present in tests\/data\/Makefile.inc//' diff --git a/meta-openbmc-mods/meta-common/recipes-support/curl/curl_7.83.1.bb b/meta-openbmc-mods/meta-common/recipes-support/curl/curl_8.1.0.bb index d20b3194c..0efd0de5c 100644 --- a/meta-openbmc-mods/meta-common/recipes-support/curl/curl_7.83.1.bb +++ b/meta-openbmc-mods/meta-common/recipes-support/curl/curl_8.1.0.bb @@ -3,62 +3,66 @@ DESCRIPTION = "It uses URL syntax to transfer data to and from servers. \ curl is a widely used because of its ability to be flexible and complete \ complex tasks. For example, you can use curl for things like user authentication, \ HTTP post, SSL connections, proxy support, FTP uploads, and more!" -HOMEPAGE = "http://curl.haxx.se/" -BUGTRACKER = "http://curl.haxx.se/mail/list.cgi?list=curl-tracker" +HOMEPAGE = "https://curl.se/" +BUGTRACKER = "https://github.com/curl/curl/issues" SECTION = "console/network" -LICENSE = "MIT" -LIC_FILES_CHKSUM = "file://COPYING;md5=190c514872597083303371684954f238" - -SRC_URI = "https://curl.haxx.se/download/curl-${PV}.tar.bz2 \ - file://0001-replace-krb5-config-with-pkg-config.patch \ - file://CVE-2022-32205-cookie-apply-limits.patch \ - file://CVE-2022-32206-return-error-on-too-many-compression-steps.patch \ - file://CVE-2022-32207-fopen-add-Curl_fopen-for-better-overwriting-of-fi.patch \ - file://CVE-2022-32208-krb5-return-error-properly-on-decode-errors.patch \ -" +LICENSE = "curl" +LIC_FILES_CHKSUM = "file://COPYING;md5=db8448a1e43eb2125f7740fc397db1f6" -SRC_URI[sha256sum] = "f539a36fb44a8260ec5d977e4e0dbdd2eee29ed90fcedaa9bc3c9f78a113bff0" +SRC_URI = " \ + https://curl.se/download/${BP}.tar.xz \ + file://run-ptest \ + file://disable-tests \ +" +SRC_URI[sha256sum] = "6bd80ad4f07187015911216ee7185b90d285ac5162aed1bded144f9f93232a3c" # Curl has used many names over the years... CVE_PRODUCT = "haxx:curl haxx:libcurl curl:curl curl:libcurl libcurl:libcurl daniel_stenberg:curl" -inherit autotools pkgconfig binconfig multilib_header +inherit autotools pkgconfig binconfig multilib_header ptest -PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)} ssl libidn proxy threaded-resolver verbose zlib" -PACKAGECONFIG_class-native = "ipv6 proxy ssl threaded-resolver verbose zlib" -PACKAGECONFIG_class-nativesdk = "ipv6 proxy ssl threaded-resolver verbose zlib" +# Entropy source for random PACKAGECONFIG option +RANDOM ?= "/dev/urandom" + +PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)} libidn openssl proxy random threaded-resolver verbose zlib" +PACKAGECONFIG:class-native = "ipv6 openssl proxy random threaded-resolver verbose zlib" +PACKAGECONFIG:class-nativesdk = "ipv6 openssl proxy random threaded-resolver verbose zlib" # 'ares' and 'threaded-resolver' are mutually exclusive PACKAGECONFIG[ares] = "--enable-ares,--disable-ares,c-ares,,,threaded-resolver" PACKAGECONFIG[brotli] = "--with-brotli,--without-brotli,brotli" PACKAGECONFIG[builtinmanual] = "--enable-manual,--disable-manual" +# Don't use this in production +PACKAGECONFIG[debug] = "--enable-debug,--disable-debug" PACKAGECONFIG[dict] = "--enable-dict,--disable-dict," PACKAGECONFIG[gnutls] = "--with-gnutls,--without-gnutls,gnutls" PACKAGECONFIG[gopher] = "--enable-gopher,--disable-gopher," PACKAGECONFIG[imap] = "--enable-imap,--disable-imap," PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6," PACKAGECONFIG[krb5] = "--with-gssapi,--without-gssapi,krb5" -PACKAGECONFIG[ldap] = "--enable-ldap,--disable-ldap," -PACKAGECONFIG[ldaps] = "--enable-ldaps,--disable-ldaps," +PACKAGECONFIG[ldap] = "--enable-ldap,--disable-ldap,openldap" +PACKAGECONFIG[ldaps] = "--enable-ldaps,--disable-ldaps,openldap" PACKAGECONFIG[libgsasl] = "--with-libgsasl,--without-libgsasl,libgsasl" PACKAGECONFIG[libidn] = "--with-libidn2,--without-libidn2,libidn2" PACKAGECONFIG[libssh2] = "--with-libssh2,--without-libssh2,libssh2" PACKAGECONFIG[mbedtls] = "--with-mbedtls=${STAGING_DIR_TARGET},--without-mbedtls,mbedtls" PACKAGECONFIG[mqtt] = "--enable-mqtt,--disable-mqtt," PACKAGECONFIG[nghttp2] = "--with-nghttp2,--without-nghttp2,nghttp2" +PACKAGECONFIG[openssl] = "--with-openssl,--without-openssl,openssl" PACKAGECONFIG[pop3] = "--enable-pop3,--disable-pop3," PACKAGECONFIG[proxy] = "--enable-proxy,--disable-proxy," +PACKAGECONFIG[random] = "--with-random=${RANDOM},--without-random" PACKAGECONFIG[rtmpdump] = "--with-librtmp,--without-librtmp,rtmpdump" PACKAGECONFIG[rtsp] = "--enable-rtsp,--disable-rtsp," PACKAGECONFIG[smb] = "--enable-smb,--disable-smb," PACKAGECONFIG[smtp] = "--enable-smtp,--disable-smtp," -PACKAGECONFIG[ssl] = "--with-ssl --with-random=/dev/urandom,--without-ssl,openssl" PACKAGECONFIG[nss] = "--with-nss,--without-nss,nss" PACKAGECONFIG[telnet] = "--enable-telnet,--disable-telnet," PACKAGECONFIG[tftp] = "--enable-tftp,--disable-tftp," PACKAGECONFIG[threaded-resolver] = "--enable-threaded-resolver,--disable-threaded-resolver,,,,ares" PACKAGECONFIG[verbose] = "--enable-verbose,--disable-verbose" PACKAGECONFIG[zlib] = "--with-zlib=${STAGING_LIBDIR}/../,--without-zlib,zlib" +PACKAGECONFIG[zstd] = "--with-zstd,--without-zstd,zstd" EXTRA_OECONF = " \ --disable-libcurl-option \ @@ -66,9 +70,8 @@ EXTRA_OECONF = " \ --enable-crypto-auth \ --with-ca-bundle=${sysconfdir}/ssl/certs/ca-certificates.crt \ --without-libpsl \ - --enable-debug \ --enable-optimize \ - --disable-curldebug \ + ${@'--without-ssl' if (bb.utils.filter('PACKAGECONFIG', 'gnutls mbedtls nss openssl', d) == '') else ''} \ " do_install:append:class-target() { @@ -77,15 +80,35 @@ do_install:append:class-target() { -e 's,--sysroot=${STAGING_DIR_TARGET},,g' \ -e 's,--with-libtool-sysroot=${STAGING_DIR_TARGET},,g' \ -e 's|${DEBUG_PREFIX_MAP}||g' \ + -e 's|${@" ".join(d.getVar("DEBUG_PREFIX_MAP").split())}||g' \ ${D}${bindir}/curl-config } +do_compile_ptest() { + oe_runmake test + oe_runmake -C ${B}/tests/server +} + +do_install_ptest() { + cat ${WORKDIR}/disable-tests >> ${S}/tests/data/DISABLED + rm -f ${B}/tests/configurehelp.pm + cp -rf ${B}/tests ${D}${PTEST_PATH} + cp -rf ${S}/tests ${D}${PTEST_PATH} + find ${D}${PTEST_PATH}/ -type f -name Makefile.am -o -name Makefile.in -o -name Makefile -delete + install -d ${D}${PTEST_PATH}/src + ln -sf ${bindir}/curl ${D}${PTEST_PATH}/src/curl + cp -rf ${D}${bindir}/curl-config ${D}${PTEST_PATH} +} + +RDEPENDS:${PN}-ptest += "bash perl-modules perl-module-time-hires perl-module-digest-md5 \ + perl-module-digest perl-module-ipc-open2" + PACKAGES =+ "lib${BPN}" -FILES_lib${BPN} = "${libdir}/lib*.so.*" -RRECOMMENDS_lib${BPN} += "ca-certificates" +FILES:lib${BPN} = "${libdir}/lib*.so.*" +RRECOMMENDS:lib${BPN} += "ca-certificates" -FILES_${PN} += "${datadir}/zsh" +FILES:${PN} += "${datadir}/zsh" inherit multilib_script MULTILIB_SCRIPTS = "${PN}-dev:${bindir}/curl-config" diff --git a/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-ensure-the-XATTR_NAME_CAPS-is-defined-when-it-is-use.patch b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-ensure-the-XATTR_NAME_CAPS-is-defined-when-it-is-use.patch new file mode 100644 index 000000000..05c771ac1 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-ensure-the-XATTR_NAME_CAPS-is-defined-when-it-is-use.patch @@ -0,0 +1,32 @@ +Ensure the XATTR_NAME_CAPS is defined when it is used + +Upstream-Status: Pending + +VFS_CAP_U32 can not ensure that XATTR_NAME_CAPS is defined, and failed to build +libcap-native in old release, like CentOS release 6.7 (Final), with the blow +error: + cap_file.c: In function ‘cap_get_fd’: + cap_file.c:199: error: ‘XATTR_NAME_CAPS’ undeclared (first use in this function) + cap_file.c:199: error: (Each undeclared identifier is reported only once + +Signed-off-by: Roy Li <rongqing.li@windriver.com> +--- + libcap/cap_file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcap/cap_file.c b/libcap/cap_file.c +index 40756ea..e27ca80 100644 +--- a/libcap/cap_file.c ++++ b/libcap/cap_file.c +@@ -25,7 +25,7 @@ extern int fremovexattr(int, const char *); + + #include "libcap.h" + +-#ifdef VFS_CAP_U32 ++#if defined (VFS_CAP_U32) && defined (XATTR_NAME_CAPS) + + #if VFS_CAP_U32 != __CAP_BLKS + # error VFS representation of capabilities is not the same size as kernel +-- +2.8.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-nativesdk-libcap-Raise-the-size-of-arrays-containing.patch b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-nativesdk-libcap-Raise-the-size-of-arrays-containing.patch new file mode 100644 index 000000000..2ac1e6e56 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0001-nativesdk-libcap-Raise-the-size-of-arrays-containing.patch @@ -0,0 +1,34 @@ +From 709aa8e156415215b0bb034d05b2aa2f44be044e Mon Sep 17 00:00:00 2001 +From: Hongxu Jia <hongxu.jia@windriver.com> +Date: Thu, 14 Oct 2021 15:57:36 +0800 +Subject: [PATCH] nativesdk-libcap: Raise the size of arrays containing dl + paths + +This patch puts the dynamic loader path in the binaries, SYSTEM_DIRS strings +and lengths as well as ld.so.cache path in the dynamic loader to specific +sections in memory. The sections that contain paths have been allocated a 4096 +byte section, which is the maximum path length in linux. This will allow the +relocating script to parse the ELF binary, detect the section and easily replace +the strings in a certain path. + +Upstream-Status: Inappropriate [SDK specific] + +Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> + +--- + libcap/execable.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libcap/execable.h b/libcap/execable.h +index fee17b4..5bb0c55 100644 +--- a/libcap/execable.h ++++ b/libcap/execable.h +@@ -23,7 +23,7 @@ + #endif + #define __EXECABLE_H + +-const char __execable_dl_loader[] __attribute((section(".interp"))) = ++const char __execable_dl_loader[4096] __attribute((section(".interp"))) = + SHARED_LOADER ; + + static void __execable_parse_args(int *argc_p, char ***argv_p) diff --git a/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0002-tests-do-not-run-target-executables.patch b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0002-tests-do-not-run-target-executables.patch new file mode 100644 index 000000000..20346cf2f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/libcap/files/0002-tests-do-not-run-target-executables.patch @@ -0,0 +1,30 @@ +From 10212b6d4e8843feffbeab5336342d97f3a46bb2 Mon Sep 17 00:00:00 2001 +From: Alexander Kanavin <alex.kanavin@gmail.com> +Date: Fri, 20 Dec 2019 16:54:05 +0100 +Subject: [PATCH] tests: do not run target executables + +Upstream-Status: Inappropriate [oe-core specific] +Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com> + +--- + tests/Makefile | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/tests/Makefile b/tests/Makefile +index ecb7d1b..8950c73 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -61,13 +61,11 @@ endif + + # unprivileged + run_psx_test: psx_test +- ./psx_test + + psx_test: psx_test.c $(DEPS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LINKEXTRA) $(LIBPSXLIB) + + run_libcap_psx_test: libcap_psx_test +- ./libcap_psx_test + + libcap_psx_test: libcap_psx_test.c $(DEPS) + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $< -o $@ $(LINKEXTRA) $(LIBCAPLIB) $(LIBPSXLIB) diff --git a/meta-openbmc-mods/meta-common/recipes-support/libcap/libcap_2.69.bb b/meta-openbmc-mods/meta-common/recipes-support/libcap/libcap_2.69.bb new file mode 100644 index 000000000..92fa766d3 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-support/libcap/libcap_2.69.bb @@ -0,0 +1,79 @@ +SUMMARY = "Library for getting/setting POSIX.1e capabilities" +DESCRIPTION = "A library providing the API to access POSIX capabilities. \ +These allow giving various kinds of specific privileges to individual \ +users, without giving them full root permissions." +HOMEPAGE = "http://sites.google.com/site/fullycapable/" +# no specific GPL version required +LICENSE = "BSD-3-Clause | GPL-2.0-only" +LIC_FILES_CHKSUM_PAM = "file://pam_cap/License;md5=905326f41d3d1f8df21943f9a4ed6b50" +LIC_FILES_CHKSUM = "file://License;md5=2965a646645b72ecee859b43c592dcaa \ + ${@bb.utils.contains('PACKAGECONFIG', 'pam', '${LIC_FILES_CHKSUM_PAM}', '', d)} \ + " + +DEPENDS = "hostperl-runtime-native gperf-native" + +SRC_URI = "${KERNELORG_MIRROR}/linux/libs/security/linux-privs/${BPN}2/${BPN}-${PV}.tar.xz \ + file://0001-ensure-the-XATTR_NAME_CAPS-is-defined-when-it-is-use.patch \ + file://0002-tests-do-not-run-target-executables.patch \ + " +SRC_URI:append:class-nativesdk = " \ + file://0001-nativesdk-libcap-Raise-the-size-of-arrays-containing.patch \ + " +SRC_URI[sha256sum] = "f311f8f3dad84699d0566d1d6f7ec943a9298b28f714cae3c931dfd57492d7eb" + +UPSTREAM_CHECK_URI = "https://www.kernel.org/pub/linux/libs/security/linux-privs/${BPN}2/" + +inherit lib_package + +PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'pam', d)}" +PACKAGECONFIG:class-native ??= "" + +PACKAGECONFIG[pam] = "PAM_CAP=yes,PAM_CAP=no,libpam" + +EXTRA_OEMAKE = " \ + INDENT= \ + lib='${baselib}' \ + RAISE_SETFCAP=no \ + DYNAMIC=yes \ + USE_GPERF=yes \ +" + +EXTRA_OEMAKE:append:class-target = " SYSTEM_HEADERS=${STAGING_INCDIR}" + +do_compile() { + unset CFLAGS BUILD_CFLAGS + oe_runmake \ + ${PACKAGECONFIG_CONFARGS} \ + AR="${AR}" \ + CC="${CC}" \ + RANLIB="${RANLIB}" \ + OBJCOPY="${OBJCOPY}" \ + COPTS="${CFLAGS}" \ + BUILD_COPTS="${BUILD_CFLAGS}" +} + +do_install() { + oe_runmake install \ + ${PACKAGECONFIG_CONFARGS} \ + DESTDIR="${D}" \ + prefix="${prefix}" \ + SBINDIR="${sbindir}" +} + +do_install:append() { + # Move the library to base_libdir + install -d ${D}${base_libdir} + if [ ! ${D}${libdir} -ef ${D}${base_libdir} ]; then + mv ${D}${libdir}/libcap* ${D}${base_libdir} + if [ -d ${D}${libdir}/security ]; then + mv ${D}${libdir}/security ${D}${base_libdir} + fi + fi +} + +FILES:${PN}-dev += "${base_libdir}/*.so" + +# pam files +FILES:${PN} += "${base_libdir}/security/*.so" + +BBCLASSEXTEND = "native nativesdk" |