summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core')
-rw-r--r--meta/recipes-core/base-files/base-files/hosts2
-rw-r--r--meta/recipes-core/base-passwd/base-passwd_3.5.29.bb1
-rw-r--r--meta/recipes-core/busybox/busybox.inc29
-rw-r--r--meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch51
-rw-r--r--meta/recipes-core/busybox/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch38
-rw-r--r--meta/recipes-core/busybox/busybox/0001-mktemp-add-tmpdir-option.patch81
-rw-r--r--meta/recipes-core/busybox/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch64
-rw-r--r--meta/recipes-core/busybox/busybox/CVE-2021-42374.patch53
-rw-r--r--meta/recipes-core/busybox/busybox/CVE-2021-42376.patch138
-rw-r--r--meta/recipes-core/busybox/busybox/CVE-2022-48174.patch82
-rw-r--r--meta/recipes-core/busybox/busybox_1.31.1.bb10
-rw-r--r--meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch215
-rw-r--r--meta/recipes-core/coreutils/coreutils_8.31.bb8
-rw-r--r--meta/recipes-core/dbus-wait/dbus-wait_git.bb3
-rw-r--r--meta/recipes-core/dbus/dbus-test_1.12.24.bb (renamed from meta/recipes-core/dbus/dbus-test_1.12.16.bb)42
-rw-r--r--meta/recipes-core/dbus/dbus.inc36
-rw-r--r--meta/recipes-core/dbus/dbus/CVE-2020-12049.patch78
-rw-r--r--meta/recipes-core/dbus/dbus/CVE-2023-34969.patch96
-rw-r--r--meta/recipes-core/dbus/dbus_1.12.24.bb (renamed from meta/recipes-core/dbus/dbus_1.12.16.bb)40
-rw-r--r--meta/recipes-core/dropbear/dropbear.inc11
-rw-r--r--meta/recipes-core/dropbear/dropbear/CVE-2020-36254.patch29
-rw-r--r--meta/recipes-core/dropbear/dropbear/CVE-2021-36369.patch145
-rw-r--r--meta/recipes-core/ell/ell_0.33.bb1
-rw-r--r--meta/recipes-core/expat/expat/CVE-2013-0340.patch1758
-rw-r--r--meta/recipes-core/expat/expat/CVE-2021-45960.patch65
-rw-r--r--meta/recipes-core/expat/expat/CVE-2021-46143.patch49
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-22822-27.patch257
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-23852.patch33
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-23990.patch49
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25235.patch283
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25236.patch129
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch131
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25313.patch230
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25314.patch32
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25315.patch145
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-40674.patch53
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-43680.patch33
-rw-r--r--meta/recipes-core/expat/expat/libtool-tag.patch41
-rw-r--r--meta/recipes-core/expat/expat_2.2.9.bb29
-rw-r--r--meta/recipes-core/fts/fts_1.2.7.bb3
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch129
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch170
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch249
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch131
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch298
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch54
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch101
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch76
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch101
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch100
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch59
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch63
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch36
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch38
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch38
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch100
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch43
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch232
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch27
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch42
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch57
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch265
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch55
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch290
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch89
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch255
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch154
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch103
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch210
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch417
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch113
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch80
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch396
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch49
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch394
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch97
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb38
-rw-r--r--meta/recipes-core/glib-2.0/glib.inc2
-rw-r--r--meta/recipes-core/glibc/cross-localedef-native_2.31.bb2
-rw-r--r--meta/recipes-core/glibc/glibc-version.inc2
-rw-r--r--meta/recipes-core/glibc/glibc.inc4
-rw-r--r--meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch66
-rw-r--r--meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch191
-rw-r--r--meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch206
-rw-r--r--meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch144
-rw-r--r--meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch180
-rw-r--r--meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch56
-rw-r--r--meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch124
-rw-r--r--meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch276
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2019-25013.patch135
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2020-29562.patch156
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch68
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch73
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2021-38604.patch41
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2023-0687.patch82
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2023-4813.patch986
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2023-4911.patch63
-rw-r--r--meta/recipes-core/glibc/glibc/check-test-wrapper11
-rw-r--r--meta/recipes-core/glibc/glibc_2.31.bb51
-rw-r--r--meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch2
-rw-r--r--meta/recipes-core/ifupdown/files/0001-inet6.defn-Added-1-option-to-dhclient-on-upping-an-i.patch65
-rw-r--r--meta/recipes-core/ifupdown/ifupdown_0.8.35.bb4
-rw-r--r--meta/recipes-core/images/build-appliance-image_15.0.0.bb10
-rw-r--r--meta/recipes-core/initrdscripts/files/init-install-efi.sh5
-rwxr-xr-xmeta/recipes-core/initrdscripts/initramfs-framework/finish9
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/rootfs2
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/setup-live2
-rw-r--r--meta/recipes-core/initscripts/initscripts_1.0.bb2
-rw-r--r--meta/recipes-core/kbd/kbd_2.2.0.bb1
-rw-r--r--meta/recipes-core/libxcrypt/libxcrypt.inc2
-rw-r--r--meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch813
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch89
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch35
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2021-3517.patch53
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch112
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2021-3537.patch50
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch73
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch98
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch204
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch53
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch348
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch623
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch104
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch79
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch42
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch36
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch71
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch44
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch50
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch80
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch38
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch33
-rw-r--r--meta/recipes-core/libxml/libxml2/runtest.patch45
-rw-r--r--meta/recipes-core/libxml/libxml2_2.9.10.bb46
-rw-r--r--meta/recipes-core/meta/buildtools-tarball.bb2
-rw-r--r--meta/recipes-core/meta/cve-update-db-native.bb181
-rw-r--r--meta/recipes-core/meta/cve-update-nvd2-native.bb372
-rw-r--r--meta/recipes-core/musl/libucontext_git.bb2
-rw-r--r--meta/recipes-core/musl/musl-obstack.bb2
-rw-r--r--meta/recipes-core/musl/musl-utils.bb2
-rw-r--r--meta/recipes-core/musl/musl_git.bb2
-rw-r--r--meta/recipes-core/ncurses/files/CVE-2021-39537.patch30
-rw-r--r--meta/recipes-core/ncurses/files/CVE-2022-29458.patch135
-rw-r--r--meta/recipes-core/ncurses/files/CVE-2023-29491.patch45
-rw-r--r--meta/recipes-core/ncurses/files/CVE-2023-50495.patch79
-rw-r--r--meta/recipes-core/ncurses/ncurses.inc2
-rw-r--r--meta/recipes-core/ncurses/ncurses_6.2.bb6
-rw-r--r--meta/recipes-core/os-release/os-release.bb4
-rw-r--r--meta/recipes-core/ovmf/ovmf/0001-Basetools-genffs-fix-gcc12-warning.patch49
-rw-r--r--meta/recipes-core/ovmf/ovmf/0001-Basetools-lzmaenc-fix-gcc12-warning.patch53
-rw-r--r--meta/recipes-core/ovmf/ovmf/0001-Basetools-turn-off-gcc12-warning.patch41
-rw-r--r--meta/recipes-core/ovmf/ovmf/0001-Fix-VLA-parameter-warning.patch51
-rw-r--r--meta/recipes-core/ovmf/ovmf/0001-ovmf-update-path-to-native-BaseTools.patch6
-rw-r--r--meta/recipes-core/ovmf/ovmf/0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch32
-rw-r--r--meta/recipes-core/ovmf/ovmf/0003-ovmf-enable-long-path-file.patch6
-rw-r--r--meta/recipes-core/ovmf/ovmf/0004-ovmf-Update-to-latest.patch20
-rw-r--r--meta/recipes-core/ovmf/ovmf_git.bb16
-rw-r--r--meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb1
-rw-r--r--meta/recipes-core/psplash/files/psplash-start.service1
-rw-r--r--meta/recipes-core/psplash/files/psplash-systemd.service1
-rw-r--r--meta/recipes-core/psplash/psplash_git.bb2
-rw-r--r--meta/recipes-core/systemd/systemd-conf/wired.network1
-rw-r--r--meta/recipes-core/systemd/systemd-conf_244.3.bb3
-rwxr-xr-xmeta/recipes-core/systemd/systemd-systemctl/systemctl22
-rw-r--r--meta/recipes-core/systemd/systemd.inc2
-rw-r--r--meta/recipes-core/systemd/systemd/00-create-volatile.conf1
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2018-21029.patch120
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2020-13529.patch42
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2021-33910.patch67
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch65
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch101
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch266
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2022-3821.patch47
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch115
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch264
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch182
-rw-r--r--meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch32
-rw-r--r--meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch78
-rw-r--r--meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch35
-rw-r--r--meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch285
-rw-r--r--meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch50
-rw-r--r--meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch278
-rw-r--r--meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch67
-rw-r--r--meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch35
-rw-r--r--meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch318
-rw-r--r--meta/recipes-core/systemd/systemd/systemd-pager.sh7
-rw-r--r--meta/recipes-core/systemd/systemd_244.5.bb35
-rw-r--r--meta/recipes-core/udev/eudev_3.2.9.bb1
-rw-r--r--meta/recipes-core/update-rc.d/update-rc.d_0.8.bb4
-rw-r--r--meta/recipes-core/util-linux/util-linux.inc7
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2021-37600.patch33
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2021-3995.patch139
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2021-3996.patch226
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2022-0563.patch161
-rw-r--r--meta/recipes-core/util-linux/util-linux/include-strutils-cleanup-strto-functions.patch270
-rw-r--r--meta/recipes-core/util-linux/util-linux_2.35.1.bb5
-rw-r--r--meta/recipes-core/volatile-binds/files/volatile-binds.service.in2
-rw-r--r--meta/recipes-core/zlib/zlib/CVE-2018-25032.patch347
-rw-r--r--meta/recipes-core/zlib/zlib/CVE-2022-37434.patch44
-rw-r--r--meta/recipes-core/zlib/zlib/CVE-2023-45853.patch40
-rw-r--r--meta/recipes-core/zlib/zlib_1.2.11.bb6
203 files changed, 20364 insertions, 644 deletions
diff --git a/meta/recipes-core/base-files/base-files/hosts b/meta/recipes-core/base-files/base-files/hosts
index b94f414d5c..10a5b6c704 100644
--- a/meta/recipes-core/base-files/base-files/hosts
+++ b/meta/recipes-core/base-files/base-files/hosts
@@ -1,4 +1,4 @@
1127.0.0.1 localhost.localdomain localhost 1127.0.0.1 localhost
2 2
3# The following lines are desirable for IPv6 capable hosts 3# The following lines are desirable for IPv6 capable hosts
4::1 localhost ip6-localhost ip6-loopback 4::1 localhost ip6-localhost ip6-loopback
diff --git a/meta/recipes-core/base-passwd/base-passwd_3.5.29.bb b/meta/recipes-core/base-passwd/base-passwd_3.5.29.bb
index d01cd7e297..65b3cd778d 100644
--- a/meta/recipes-core/base-passwd/base-passwd_3.5.29.bb
+++ b/meta/recipes-core/base-passwd/base-passwd_3.5.29.bb
@@ -1,5 +1,6 @@
1SUMMARY = "Base system master password/group files" 1SUMMARY = "Base system master password/group files"
2DESCRIPTION = "The master copies of the user database files (/etc/passwd and /etc/group). The update-passwd tool is also provided to keep the system databases synchronized with these master files." 2DESCRIPTION = "The master copies of the user database files (/etc/passwd and /etc/group). The update-passwd tool is also provided to keep the system databases synchronized with these master files."
3HOMEPAGE = "https://launchpad.net/base-passwd"
3SECTION = "base" 4SECTION = "base"
4LICENSE = "GPLv2" 5LICENSE = "GPLv2"
5LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" 6LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a"
diff --git a/meta/recipes-core/busybox/busybox.inc b/meta/recipes-core/busybox/busybox.inc
index e0522be729..f0c5666f47 100644
--- a/meta/recipes-core/busybox/busybox.inc
+++ b/meta/recipes-core/busybox/busybox.inc
@@ -139,6 +139,10 @@ do_configure () {
139 do_prepare_config 139 do_prepare_config
140 merge_config.sh -m .config ${@" ".join(find_cfgs(d))} 140 merge_config.sh -m .config ${@" ".join(find_cfgs(d))}
141 cml1_do_configure 141 cml1_do_configure
142
143 # Save a copy of .config and autoconf.h.
144 cp .config .config.orig
145 cp include/autoconf.h include/autoconf.h.orig
142} 146}
143 147
144do_compile() { 148do_compile() {
@@ -146,13 +150,17 @@ do_compile() {
146 if [ "${BUILD_REPRODUCIBLE_BINARIES}" = "1" ]; then 150 if [ "${BUILD_REPRODUCIBLE_BINARIES}" = "1" ]; then
147 export KCONFIG_NOTIMESTAMP=1 151 export KCONFIG_NOTIMESTAMP=1
148 fi 152 fi
153
154 # Ensure we start do_compile with the original .config and autoconf.h.
155 # These files should always have matching timestamps.
156 cp .config.orig .config
157 cp include/autoconf.h.orig include/autoconf.h
158
149 if [ "${BUSYBOX_SPLIT_SUID}" = "1" -a x`grep "CONFIG_FEATURE_INDIVIDUAL=y" .config` = x ]; then 159 if [ "${BUSYBOX_SPLIT_SUID}" = "1" -a x`grep "CONFIG_FEATURE_INDIVIDUAL=y" .config` = x ]; then
160 # Guard againt interrupted do_compile: clean temporary files.
161 rm -f .config.app.suid .config.app.nosuid .config.disable.apps .config.nonapps
162
150 # split the .config into two parts, and make two busybox binaries 163 # split the .config into two parts, and make two busybox binaries
151 if [ -e .config.orig ]; then
152 # Need to guard again an interrupted do_compile - restore any backup
153 cp .config.orig .config
154 fi
155 cp .config .config.orig
156 oe_runmake busybox.cfg.suid 164 oe_runmake busybox.cfg.suid
157 oe_runmake busybox.cfg.nosuid 165 oe_runmake busybox.cfg.nosuid
158 166
@@ -189,15 +197,18 @@ do_compile() {
189 bbfatal "busybox suid binary incorrectly provides /bin/sh" 197 bbfatal "busybox suid binary incorrectly provides /bin/sh"
190 fi 198 fi
191 199
192 # copy .config.orig back to .config, because the install process may check this file
193 cp .config.orig .config
194 # cleanup 200 # cleanup
195 rm .config.orig .config.app.suid .config.app.nosuid .config.disable.apps .config.nonapps 201 rm .config.app.suid .config.app.nosuid .config.disable.apps .config.nonapps
196 else 202 else
197 oe_runmake busybox_unstripped 203 oe_runmake busybox_unstripped
198 cp busybox_unstripped busybox 204 cp busybox_unstripped busybox
199 oe_runmake busybox.links 205 oe_runmake busybox.links
200 fi 206 fi
207
208 # restore original .config and autoconf.h, because the install process
209 # may check these files
210 cp .config.orig .config
211 cp include/autoconf.h.orig include/autoconf.h
201} 212}
202 213
203do_install () { 214do_install () {
@@ -348,7 +359,7 @@ do_install_ptest () {
348 # These access the internet which is not guaranteed to work on machines running the tests 359 # These access the internet which is not guaranteed to work on machines running the tests
349 rm -rf ${D}${PTEST_PATH}/testsuite/wget 360 rm -rf ${D}${PTEST_PATH}/testsuite/wget
350 sort ${B}/.config > ${D}${PTEST_PATH}/.config 361 sort ${B}/.config > ${D}${PTEST_PATH}/.config
351 ln -s /bin/busybox ${D}${PTEST_PATH}/busybox 362 ln -s ${base_bindir}/busybox ${D}${PTEST_PATH}/busybox
352} 363}
353 364
354inherit update-alternatives 365inherit update-alternatives
diff --git a/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch b/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch
new file mode 100644
index 0000000000..b75f0907e7
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch
@@ -0,0 +1,51 @@
1From fe791386ebc270219ca00406c9fdadc5130b64ee Mon Sep 17 00:00:00 2001
2From: Samuel Sapalski <samuel.sapalski@nokia.com>
3Date: Wed, 3 Mar 2021 16:31:22 +0100
4Subject: [PATCH] decompress_gunzip: Fix DoS if gzip is corrupt
5
6On certain corrupt gzip files, huft_build will set the error bit on
7the result pointer. If afterwards abort_unzip is called huft_free
8might run into a segmentation fault or an invalid pointer to
9free(p).
10
11In order to mitigate this, we check in huft_free if the error bit
12is set and clear it before the linked list is freed.
13
14Signed-off-by: Samuel Sapalski <samuel.sapalski@nokia.com>
15Signed-off-by: Peter Kaestle <peter.kaestle@nokia.com>
16Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
17
18Upstream-Status: Backport
19CVE: CVE-2021-28831
20Comment: One hunk from this patch is removed as it was not relevant.
21Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
22Signed-off-by: Akash Hadke <Akash.Hadke@kpit.com>
23---
24 archival/libarchive/decompress_gunzip.c | 12 ++++++++++--
25 1 file changed, 10 insertions(+), 2 deletions(-)
26
27diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c
28index eb3b64930..e93cd5005 100644
29--- a/archival/libarchive/decompress_gunzip.c
30+++ b/archival/libarchive/decompress_gunzip.c
31@@ -220,10 +220,20 @@ static const uint8_t border[] ALIGN1 = {
32 * each table.
33 * t: table to free
34 */
35+#define BAD_HUFT(p) ((uintptr_t)(p) & 1)
36+#define ERR_RET ((huft_t*)(uintptr_t)1)
37 static void huft_free(huft_t *p)
38 {
39 huft_t *q;
40
41+ /*
42+ * If 'p' has the error bit set we have to clear it, otherwise we might run
43+ * into a segmentation fault or an invalid pointer to free(p)
44+ */
45+ if (BAD_HUFT(p)) {
46+ p = (huft_t*)((uintptr_t)(p) ^ (uintptr_t)(ERR_RET));
47+ }
48+
49 /* Go through linked list, freeing from the malloced (t[-1]) address. */
50 while (p) {
51 q = (--p)->v.t;
diff --git a/meta/recipes-core/busybox/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch b/meta/recipes-core/busybox/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch
new file mode 100644
index 0000000000..18bf5f19e4
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch
@@ -0,0 +1,38 @@
1From c7e181fdf58c392e06ab805e2c044c3e57d5445a Mon Sep 17 00:00:00 2001
2From: Ariadne Conill <ariadne@dereferenced.org>
3Date: Sun, 3 Apr 2022 12:14:33 +0000
4Subject: [PATCH] libbb: sockaddr2str: ensure only printable characters are
5 returned for the hostname part
6
7CVE: CVE-2022-28391
8Upstream-Status: Pending
9Signed-off-by: Ariadne Conill <ariadne@dereferenced.org>
10Signed-off-by: Steve Sakoman <steve@sakoman.com>
11---
12 libbb/xconnect.c | 5 +++--
13 1 file changed, 3 insertions(+), 2 deletions(-)
14
15diff --git a/libbb/xconnect.c b/libbb/xconnect.c
16index eb2871cb1..b5520bb21 100644
17--- a/libbb/xconnect.c
18+++ b/libbb/xconnect.c
19@@ -501,8 +501,9 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags)
20 );
21 if (rc)
22 return NULL;
23+ /* ensure host contains only printable characters */
24 if (flags & IGNORE_PORT)
25- return xstrdup(host);
26+ return xstrdup(printable_string(host));
27 #if ENABLE_FEATURE_IPV6
28 if (sa->sa_family == AF_INET6) {
29 if (strchr(host, ':')) /* heh, it's not a resolved hostname */
30@@ -513,7 +514,7 @@ static char* FAST_FUNC sockaddr2str(const struct sockaddr *sa, int flags)
31 #endif
32 /* For now we don't support anything else, so it has to be INET */
33 /*if (sa->sa_family == AF_INET)*/
34- return xasprintf("%s:%s", host, serv);
35+ return xasprintf("%s:%s", printable_string(host), serv);
36 /*return xstrdup(host);*/
37 }
38
diff --git a/meta/recipes-core/busybox/busybox/0001-mktemp-add-tmpdir-option.patch b/meta/recipes-core/busybox/busybox/0001-mktemp-add-tmpdir-option.patch
new file mode 100644
index 0000000000..4a1960dff2
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-mktemp-add-tmpdir-option.patch
@@ -0,0 +1,81 @@
1From ceb378209f953ea745ed93a8645567196380ce3c Mon Sep 17 00:00:00 2001
2From: Andrej Valek <andrej.valek@siemens.com>
3Date: Thu, 24 Jun 2021 19:13:22 +0200
4Subject: [PATCH] mktemp: add tmpdir option
5
6Make mktemp more compatible with coreutils.
7- add "--tmpdir" option
8- add long variants for "d,q,u" options
9
10Upstream-Status: Submitted [http://lists.busybox.net/pipermail/busybox/2021-June/088932.html]
11
12Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
13Signed-off-by: Peter Marko <peter.marko@siemens.com>
14---
15 coreutils/mktemp.c | 26 ++++++++++++++++++--------
16 1 file changed, 18 insertions(+), 8 deletions(-)
17
18diff --git a/coreutils/mktemp.c b/coreutils/mktemp.c
19index 5393320a5..05c6d98c6 100644
20--- a/coreutils/mktemp.c
21+++ b/coreutils/mktemp.c
22@@ -39,16 +39,17 @@
23 //kbuild:lib-$(CONFIG_MKTEMP) += mktemp.o
24
25 //usage:#define mktemp_trivial_usage
26-//usage: "[-dt] [-p DIR] [TEMPLATE]"
27+//usage: "[-dt] [-p DIR, --tmpdir[=DIR]] [TEMPLATE]"
28 //usage:#define mktemp_full_usage "\n\n"
29 //usage: "Create a temporary file with name based on TEMPLATE and print its name.\n"
30 //usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n"
31 //usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n"
32-//usage: "\n -d Make directory, not file"
33-//usage: "\n -q Fail silently on errors"
34-//usage: "\n -t Prepend base directory name to TEMPLATE"
35-//usage: "\n -p DIR Use DIR as a base directory (implies -t)"
36-//usage: "\n -u Do not create anything; print a name"
37+//usage: "\n -d Make directory, not file"
38+//usage: "\n -q Fail silently on errors"
39+//usage: "\n -t Prepend base directory name to TEMPLATE"
40+//usage: "\n -p DIR, --tmpdir[=DIR] Use DIR as a base directory (implies -t)"
41+//usage: "\n For --tmpdir is a optional one."
42+//usage: "\n -u Do not create anything; print a name"
43 //usage: "\n"
44 //usage: "\nBase directory is: -p DIR, else $TMPDIR, else /tmp"
45 //usage:
46@@ -72,13 +73,22 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
47 OPT_t = 1 << 2,
48 OPT_p = 1 << 3,
49 OPT_u = 1 << 4,
50+ OPT_td = 1 << 5,
51 };
52
53 path = getenv("TMPDIR");
54 if (!path || path[0] == '\0')
55 path = "/tmp";
56
57- opts = getopt32(argv, "^" "dqtp:u" "\0" "?1"/*1 arg max*/, &path);
58+ opts = getopt32long(argv, "^"
59+ "dqtp:u\0"
60+ "?1" /* 1 arg max */,
61+ "directory\0" No_argument "d"
62+ "quiet\0" No_argument "q"
63+ "dry-run\0" No_argument "u"
64+ "tmpdir\0" Optional_argument "\xff"
65+ , &path, &path
66+ );
67
68 chp = argv[optind];
69 if (!chp) {
70@@ -95,7 +105,7 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv)
71 goto error;
72 }
73 #endif
74- if (opts & (OPT_t|OPT_p))
75+ if (opts & (OPT_t|OPT_p|OPT_td))
76 chp = concat_path_file(path, chp);
77
78 if (opts & OPT_u) {
79--
802.11.0
81
diff --git a/meta/recipes-core/busybox/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch b/meta/recipes-core/busybox/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch
new file mode 100644
index 0000000000..2c9da33a51
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0002-nslookup-sanitize-all-printed-strings-with-printable.patch
@@ -0,0 +1,64 @@
1From f8ad7c331b25ba90fd296b37c443b4114cb196e2 Mon Sep 17 00:00:00 2001
2From: Ariadne Conill <ariadne@dereferenced.org>
3Date: Sun, 3 Apr 2022 12:16:45 +0000
4Subject: [PATCH] nslookup: sanitize all printed strings with printable_string
5
6Otherwise, terminal sequences can be injected, which enables various terminal injection
7attacks from DNS results.
8
9MJ: One chunk wasn't applicable on 1.31.1 version, because parsing of
10SRV records was added only in newer 1.32.0 with:
11 commit 6b4960155e94076bf25518e4e268a7a5f849308e
12 Author: Jo-Philipp Wich <jo@mein.io>
13 Date: Thu Jun 27 17:27:29 2019 +0200
14
15 nslookup: implement support for SRV records
16
17CVE: CVE-2022-28391
18Upstream-Status: Pending
19Signed-off-by: Ariadne Conill <ariadne@dereferenced.org>
20Signed-off-by: Steve Sakoman <steve@sakoman.com>
21---
22 networking/nslookup.c | 8 ++++----
23 1 file changed, 4 insertions(+), 4 deletions(-)
24
25diff --git a/networking/nslookup.c b/networking/nslookup.c
26index 24e09d4f0..89b9c8a13 100644
27--- a/networking/nslookup.c
28+++ b/networking/nslookup.c
29@@ -404,7 +404,7 @@ static int parse_reply(const unsigned char *msg, size_t len)
30 //printf("Unable to uncompress domain: %s\n", strerror(errno));
31 return -1;
32 }
33- printf(format, ns_rr_name(rr), dname);
34+ printf(format, ns_rr_name(rr), printable_string(dname));
35 break;
36
37 case ns_t_mx:
38@@ -419,7 +419,7 @@ static int parse_reply(const unsigned char *msg, size_t len)
39 //printf("Cannot uncompress MX domain: %s\n", strerror(errno));
40 return -1;
41 }
42- printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, dname);
43+ printf("%s\tmail exchanger = %d %s\n", ns_rr_name(rr), n, printable_string(dname));
44 break;
45
46 case ns_t_txt:
47@@ -431,7 +431,7 @@ static int parse_reply(const unsigned char *msg, size_t len)
48 if (n > 0) {
49 memset(dname, 0, sizeof(dname));
50 memcpy(dname, ns_rr_rdata(rr) + 1, n);
51- printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), dname);
52+ printf("%s\ttext = \"%s\"\n", ns_rr_name(rr), printable_string(dname));
53 }
54 break;
55
56@@ -461,7 +461,7 @@ static int parse_reply(const unsigned char *msg, size_t len)
57 return -1;
58 }
59
60- printf("\tmail addr = %s\n", dname);
61+ printf("\tmail addr = %s\n", printable_string(dname));
62 cp += n;
63
64 printf("\tserial = %lu\n", ns_get32(cp));
diff --git a/meta/recipes-core/busybox/busybox/CVE-2021-42374.patch b/meta/recipes-core/busybox/busybox/CVE-2021-42374.patch
new file mode 100644
index 0000000000..aef8a3db85
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/CVE-2021-42374.patch
@@ -0,0 +1,53 @@
1From 04f052c56ded5ab6a904e3a264a73dc0412b2e78 Mon Sep 17 00:00:00 2001
2From: Denys Vlasenko <vda.linux@googlemail.com>
3Date: Tue, 15 Jun 2021 15:07:57 +0200
4Subject: [PATCH] unlzma: fix a case where we could read before beginning of
5 buffer
6Cc: pavel@zhukoff.net
7
8Testcase:
9
10 21 01 01 00 00 00 00 00 e7 01 01 01 ef 00 df b6
11 00 17 02 10 11 0f ff 00 16 00 00
12
13Unfortunately, the bug is not reliably causing a segfault,
14the behavior depends on what's in memory before the buffer.
15
16function old new delta
17unpack_lzma_stream 2762 2768 +6
18
19Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
20
21Signed-off-by: Pavel Zhukov <pavel.zhukov@huawei.com>
22
23CVE: CVE-2021-42374
24Upstream-Status: Backport [https://git.busybox.net/busybox/commit/?h=1_33_stable&id=d326be2850ea2bd78fe2c22d6c45c3b861d82937]
25Comment: testdata dropped because of binary format
26
27---
28 archival/libarchive/decompress_unlzma.c | 5 ++++-
29 testsuite/unlzma.tests | 17 +++++++++++++----
30 testsuite/unlzma_issue_3.lzma | Bin 0 -> 27 bytes
31 3 files changed, 17 insertions(+), 5 deletions(-)
32 create mode 100644 testsuite/unlzma_issue_3.lzma
33
34diff --git a/archival/libarchive/decompress_unlzma.c b/archival/libarchive/decompress_unlzma.c
35index 0744f231a1d64d92676b0cada2342f88f3b39b31..fb5aac8fe9ea0c53e0c2d7a7cbd05a753e39bc9d 100644
36--- a/archival/libarchive/decompress_unlzma.c
37+++ b/archival/libarchive/decompress_unlzma.c
38@@ -290,8 +290,11 @@ unpack_lzma_stream(transformer_state_t *xstate)
39 uint32_t pos;
40
41 pos = buffer_pos - rep0;
42- if ((int32_t)pos < 0)
43+ if ((int32_t)pos < 0) {
44 pos += header.dict_size;
45+ if ((int32_t)pos < 0)
46+ goto bad;
47+ }
48 match_byte = buffer[pos];
49 do {
50 int bit;
51--
522.34.0
53
diff --git a/meta/recipes-core/busybox/busybox/CVE-2021-42376.patch b/meta/recipes-core/busybox/busybox/CVE-2021-42376.patch
new file mode 100644
index 0000000000..c913eaee9c
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/CVE-2021-42376.patch
@@ -0,0 +1,138 @@
1From 56a335378ac100d51c30b21eee499a2effa37fba Mon Sep 17 00:00:00 2001
2From: Denys Vlasenko <vda.linux@googlemail.com>
3Date: Tue, 15 Jun 2021 16:05:57 +0200
4Subject: hush: fix handling of \^C and "^C"
5
6function old new delta
7parse_stream 2238 2252 +14
8encode_string 243 256 +13
9------------------------------------------------------------------------------
10(add/remove: 0/0 grow/shrink: 2/0 up/down: 27/0) Total: 27 bytes
11
12Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
13(cherry picked from commit 1b7a9b68d0e9aa19147d7fda16eb9a6b54156985)
14
15Signed-off-by: Pavel Zhukov <pavel.zhukov@huawei.com>
16
17CVE: CVE-2021-42376
18Upstream-Status: Backport [https://git.busybox.net/busybox/patch/?id=56a335378ac100d51c30b21eee499a2effa37fba]
19Comment: No changes in any hunk
20---
21 shell/ash_test/ash-misc/control_char3.right | 1 +
22 shell/ash_test/ash-misc/control_char3.tests | 2 ++
23 shell/ash_test/ash-misc/control_char4.right | 1 +
24 shell/ash_test/ash-misc/control_char4.tests | 2 ++
25 shell/hush.c | 11 +++++++++++
26 shell/hush_test/hush-misc/control_char3.right | 1 +
27 shell/hush_test/hush-misc/control_char3.tests | 2 ++
28 shell/hush_test/hush-misc/control_char4.right | 1 +
29 shell/hush_test/hush-misc/control_char4.tests | 2 ++
30 9 files changed, 23 insertions(+)
31 create mode 100644 shell/ash_test/ash-misc/control_char3.right
32 create mode 100755 shell/ash_test/ash-misc/control_char3.tests
33 create mode 100644 shell/ash_test/ash-misc/control_char4.right
34 create mode 100755 shell/ash_test/ash-misc/control_char4.tests
35 create mode 100644 shell/hush_test/hush-misc/control_char3.right
36 create mode 100755 shell/hush_test/hush-misc/control_char3.tests
37 create mode 100644 shell/hush_test/hush-misc/control_char4.right
38 create mode 100755 shell/hush_test/hush-misc/control_char4.tests
39
40diff --git a/shell/ash_test/ash-misc/control_char3.right b/shell/ash_test/ash-misc/control_char3.right
41new file mode 100644
42index 000000000..283e02cbb
43--- /dev/null
44+++ b/shell/ash_test/ash-misc/control_char3.right
45@@ -0,0 +1 @@
46+SHELL: line 1: : not found
47diff --git a/shell/ash_test/ash-misc/control_char3.tests b/shell/ash_test/ash-misc/control_char3.tests
48new file mode 100755
49index 000000000..4359db3f3
50--- /dev/null
51+++ b/shell/ash_test/ash-misc/control_char3.tests
52@@ -0,0 +1,2 @@
53+# (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages)
54+$THIS_SH -c '\' SHELL
55diff --git a/shell/ash_test/ash-misc/control_char4.right b/shell/ash_test/ash-misc/control_char4.right
56new file mode 100644
57index 000000000..2bf18e684
58--- /dev/null
59+++ b/shell/ash_test/ash-misc/control_char4.right
60@@ -0,0 +1 @@
61+SHELL: line 1: -: not found
62diff --git a/shell/ash_test/ash-misc/control_char4.tests b/shell/ash_test/ash-misc/control_char4.tests
63new file mode 100755
64index 000000000..48010f154
65--- /dev/null
66+++ b/shell/ash_test/ash-misc/control_char4.tests
67@@ -0,0 +1,2 @@
68+# (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages)
69+$THIS_SH -c '"-"' SHELL
70diff --git a/shell/hush.c b/shell/hush.c
71index 9fead37da..249728b9d 100644
72--- a/shell/hush.c
73+++ b/shell/hush.c
74@@ -5235,6 +5235,11 @@ static int encode_string(o_string *as_string,
75 }
76 #endif
77 o_addQchr(dest, ch);
78+ if (ch == SPECIAL_VAR_SYMBOL) {
79+ /* Convert "^C" to corresponding special variable reference */
80+ o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
81+ o_addchr(dest, SPECIAL_VAR_SYMBOL);
82+ }
83 goto again;
84 #undef as_string
85 }
86@@ -5346,6 +5351,11 @@ static struct pipe *parse_stream(char **pstring,
87 if (ch == '\n')
88 continue; /* drop \<newline>, get next char */
89 nommu_addchr(&ctx.as_string, '\\');
90+ if (ch == SPECIAL_VAR_SYMBOL) {
91+ nommu_addchr(&ctx.as_string, ch);
92+ /* Convert \^C to corresponding special variable reference */
93+ goto case_SPECIAL_VAR_SYMBOL;
94+ }
95 o_addchr(&ctx.word, '\\');
96 if (ch == EOF) {
97 /* Testcase: eval 'echo Ok\' */
98@@ -5670,6 +5680,7 @@ static struct pipe *parse_stream(char **pstring,
99 /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
100
101 switch (ch) {
102+ case_SPECIAL_VAR_SYMBOL:
103 case SPECIAL_VAR_SYMBOL:
104 /* Convert raw ^C to corresponding special variable reference */
105 o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
106diff --git a/shell/hush_test/hush-misc/control_char3.right b/shell/hush_test/hush-misc/control_char3.right
107new file mode 100644
108index 000000000..94b4f8699
109--- /dev/null
110+++ b/shell/hush_test/hush-misc/control_char3.right
111@@ -0,0 +1 @@
112+hush: can't execute '': No such file or directory
113diff --git a/shell/hush_test/hush-misc/control_char3.tests b/shell/hush_test/hush-misc/control_char3.tests
114new file mode 100755
115index 000000000..4359db3f3
116--- /dev/null
117+++ b/shell/hush_test/hush-misc/control_char3.tests
118@@ -0,0 +1,2 @@
119+# (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages)
120+$THIS_SH -c '\' SHELL
121diff --git a/shell/hush_test/hush-misc/control_char4.right b/shell/hush_test/hush-misc/control_char4.right
122new file mode 100644
123index 000000000..698e21427
124--- /dev/null
125+++ b/shell/hush_test/hush-misc/control_char4.right
126@@ -0,0 +1 @@
127+hush: can't execute '-': No such file or directory
128diff --git a/shell/hush_test/hush-misc/control_char4.tests b/shell/hush_test/hush-misc/control_char4.tests
129new file mode 100755
130index 000000000..48010f154
131--- /dev/null
132+++ b/shell/hush_test/hush-misc/control_char4.tests
133@@ -0,0 +1,2 @@
134+# (set argv0 to "SHELL" to avoid "/path/to/shell: blah" in error messages)
135+$THIS_SH -c '"-"' SHELL
136--
137cgit v1.2.3
138
diff --git a/meta/recipes-core/busybox/busybox/CVE-2022-48174.patch b/meta/recipes-core/busybox/busybox/CVE-2022-48174.patch
new file mode 100644
index 0000000000..dfba2a7e0f
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/CVE-2022-48174.patch
@@ -0,0 +1,82 @@
1From c18ebf861528ef24958dd99a146482d2a40014c7 Mon Sep 17 00:00:00 2001
2From: Denys Vlasenko <vda.linux@googlemail.com>
3Date: Mon, 12 Jun 2023 17:48:47 +0200
4Subject: [PATCH] shell: avoid segfault on ${0::0/0~09J}. Closes 15216
5
6function old new delta
7evaluate_string 1011 1053 +42
8
9CVE: CVE-2022-48174
10Upstream-Status: Backport [d417193cf37ca1005830d7e16f5fa7e1d8a44209]
11Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
12---
13 shell/math.c | 39 +++++++++++++++++++++++++++++++++++----
14 1 file changed, 35 insertions(+), 4 deletions(-)
15
16diff --git a/shell/math.c b/shell/math.c
17index af1ab55c0..79824e81f 100644
18--- a/shell/math.c
19+++ b/shell/math.c
20@@ -578,6 +578,28 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
21 # endif
22 #endif
23
24+//TODO: much better estimation than expr_len/2? Such as:
25+//static unsigned estimate_nums_and_names(const char *expr)
26+//{
27+// unsigned count = 0;
28+// while (*(expr = skip_whitespace(expr)) != '\0') {
29+// const char *p;
30+// if (isdigit(*expr)) {
31+// while (isdigit(*++expr))
32+// continue;
33+// count++;
34+// continue;
35+// }
36+// p = endofname(expr);
37+// if (p != expr) {
38+// expr = p;
39+// count++;
40+// continue;
41+// }
42+// }
43+// return count;
44+//}
45+
46 static arith_t FAST_FUNC
47 evaluate_string(arith_state_t *math_state, const char *expr)
48 {
49@@ -585,10 +607,12 @@ evaluate_string(arith_state_t *math_state, const char *expr)
50 const char *errmsg;
51 const char *start_expr = expr = skip_whitespace(expr);
52 unsigned expr_len = strlen(expr) + 2;
53- /* Stack of integers */
54- /* The proof that there can be no more than strlen(startbuf)/2+1
55- * integers in any given correct or incorrect expression
56- * is left as an exercise to the reader. */
57+ /* Stack of integers/names */
58+ /* There can be no more than strlen(startbuf)/2+1
59+ * integers/names in any given correct or incorrect expression.
60+ * (modulo "09v09v09v09v09v" case,
61+ * but we have code to detect that early)
62+ */
63 var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
64 var_or_num_t *numstackptr = numstack;
65 /* Stack of operator tokens */
66@@ -657,6 +681,13 @@ evaluate_string(arith_state_t *math_state, const char *expr)
67 numstackptr->var = NULL;
68 errno = 0;
69 numstackptr->val = strto_arith_t(expr, (char**) &expr);
70+ /* A number can't be followed by another number, or a variable name.
71+ * We'd catch this later anyway, but this would require numstack[]
72+ * to be twice as deep to handle strings where _every_ char is
73+ * a new number or name. Example: 09v09v09v09v09v09v09v09v09v
74+ */
75+ if (isalnum(*expr) || *expr == '_')
76+ goto err;
77 if (errno)
78 numstackptr->val = 0; /* bash compat */
79 goto num;
80--
812.40.1
82
diff --git a/meta/recipes-core/busybox/busybox_1.31.1.bb b/meta/recipes-core/busybox/busybox_1.31.1.bb
index 7563368287..94aa1467df 100644
--- a/meta/recipes-core/busybox/busybox_1.31.1.bb
+++ b/meta/recipes-core/busybox/busybox_1.31.1.bb
@@ -50,7 +50,15 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
50 file://0001-sysctl-ignore-EIO-of-stable_secret-below-proc-sys-ne.patch \ 50 file://0001-sysctl-ignore-EIO-of-stable_secret-below-proc-sys-ne.patch \
51 file://busybox-CVE-2018-1000500.patch \ 51 file://busybox-CVE-2018-1000500.patch \
52 file://0001-hwclock-make-glibc-2.31-compatible.patch \ 52 file://0001-hwclock-make-glibc-2.31-compatible.patch \
53" 53 file://0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch \
54 file://0001-mktemp-add-tmpdir-option.patch \
55 file://CVE-2021-42374.patch \
56 file://CVE-2021-42376.patch \
57 file://CVE-2021-423xx-awk.patch \
58 file://CVE-2022-48174.patch \
59 file://0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch \
60 file://0002-nslookup-sanitize-all-printed-strings-with-printable.patch \
61 "
54SRC_URI_append_libc-musl = " file://musl.cfg " 62SRC_URI_append_libc-musl = " file://musl.cfg "
55 63
56SRC_URI[tarball.md5sum] = "70913edaf2263a157393af07565c17f0" 64SRC_URI[tarball.md5sum] = "70913edaf2263a157393af07565c17f0"
diff --git a/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch b/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch
new file mode 100644
index 0000000000..7e3d47b88c
--- /dev/null
+++ b/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch
@@ -0,0 +1,215 @@
1From a21708eb8d07b4a6dbc1d3e4ace4c5721515a84c Mon Sep 17 00:00:00 2001
2From: Sana Kazi <Sana.Kazi@kpit.com>
3Date: Wed, 8 Dec 2021 12:25:34 +0530
4Subject: [PATCH] busybox: Fix multiple security issues in awk
5
6Description: fix multiple security issues in awk
7Origin: backported awk.c from busybox 1.34.1
8
9CVE: CVE-2021-42378
10CVE: CVE-2021-42379
11CVE: CVE-2021-42380
12CVE: CVE-2021-42381
13CVE: CVE-2021-42382
14CVE: CVE-2021-42384
15CVE: CVE-2021-42385
16CVE: CVE-2021-42386
17
18Upstream-Status: Backport [https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/busybox/1:1.30.1-6ubuntu3.1/busybox_1.30.1-6ubuntu3.1.debian.tar.xz]
19
20Comment: Refreshed first hunk and removed few hunks as they are already present in source.
21
22Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
23Signed-off-by: Ranjitsinh Rathod <Ranjitsinh.Rathod@kpit.com>
24
25---
26 editors/awk.c | 80 ++++++++++++++++++++++++++++++++++++++-------------
27 1 file changed, 60 insertions(+), 20 deletions(-)
28
29diff --git a/editors/awk.c b/editors/awk.c
30index d25508e..4e4f282 100644
31--- a/editors/awk.c
32+++ b/editors/awk.c
33@@ -272,7 +272,8 @@ typedef struct tsplitter_s {
34 /* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
35 /* operator is inserted between them */
36 #define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
37- | TC_STRING | TC_NUMBER | TC_UOPPOST)
38+ | TC_STRING | TC_NUMBER | TC_UOPPOST \
39+ | TC_LENGTH)
40 #define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
41
42 #define OF_RES1 0x010000
43@@ -404,7 +405,7 @@ static const char tokenlist[] ALIGN1 =
44
45 #define OC_B OC_BUILTIN
46
47-static const uint32_t tokeninfo[] = {
48+static const uint32_t tokeninfo[] ALIGN4 = {
49 0,
50 0,
51 OC_REGEXP,
52@@ -1070,8 +1071,10 @@ static uint32_t next_token(uint32_t expected)
53 const uint32_t *ti;
54
55 if (t_rollback) {
56+ debug_printf_parse("%s: using rolled-back token\n", __func__);
57 t_rollback = FALSE;
58 } else if (concat_inserted) {
59+ debug_printf_parse("%s: using concat-inserted token\n", __func__);
60 concat_inserted = FALSE;
61 t_tclass = save_tclass;
62 t_info = save_info;
63@@ -1200,7 +1203,11 @@ static uint32_t next_token(uint32_t expected)
64 goto readnext;
65
66 /* insert concatenation operator when needed */
67- if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) {
68+ debug_printf_parse("%s: %x %x %x concat_inserted?\n", __func__,
69+ (ltclass & TC_CONCAT1), (tc & TC_CONCAT2), (expected & TC_BINOP));
70+ if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)
71+ && !(ltclass == TC_LENGTH && tc == TC_SEQSTART) /* but not for "length(..." */
72+ ) {
73 concat_inserted = TRUE;
74 save_tclass = tc;
75 save_info = t_info;
76@@ -1208,6 +1215,7 @@ static uint32_t next_token(uint32_t expected)
77 t_info = OC_CONCAT | SS | P(35);
78 }
79
80+ debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, t_tclass);
81 t_tclass = tc;
82 }
83 ltclass = t_tclass;
84@@ -1218,6 +1226,7 @@ static uint32_t next_token(uint32_t expected)
85 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
86 }
87
88+ debug_printf_parse("%s: returning, ltclass:%x t_double:%f\n", __func__, ltclass, t_double);
89 return ltclass;
90 #undef concat_inserted
91 #undef save_tclass
92@@ -1282,7 +1291,7 @@ static node *parse_expr(uint32_t iexp)
93 glptr = NULL;
94
95 } else if (tc & (TC_BINOP | TC_UOPPOST)) {
96- debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__);
97+ debug_printf_parse("%s: TC_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
98 /* for binary and postfix-unary operators, jump back over
99 * previous operators with higher priority */
100 vn = cn;
101@@ -1350,8 +1359,10 @@ static node *parse_expr(uint32_t iexp)
102 v = cn->l.v = xzalloc(sizeof(var));
103 if (tc & TC_NUMBER)
104 setvar_i(v, t_double);
105- else
106+ else {
107 setvar_s(v, t_string);
108+ xtc &= ~TC_UOPPOST; /* "str"++ is not allowed */
109+ }
110 break;
111
112 case TC_REGEXP:
113@@ -1387,7 +1398,12 @@ static node *parse_expr(uint32_t iexp)
114
115 case TC_LENGTH:
116 debug_printf_parse("%s: TC_LENGTH\n", __func__);
117- next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM);
118+ next_token(TC_SEQSTART /* length(...) */
119+ | TC_OPTERM /* length; (or newline)*/
120+ | TC_GRPTERM /* length } */
121+ | TC_BINOPX /* length <op> NUM */
122+ | TC_COMMA /* print length, 1 */
123+ );
124 rollback_token();
125 if (t_tclass & TC_SEQSTART) {
126 /* It was a "(" token. Handle just like TC_BUILTIN */
127@@ -1747,12 +1763,34 @@ static void fsrealloc(int size)
128 nfields = size;
129 }
130
131+static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[])
132+{
133+ int r = regexec(preg, s, 1, pmatch, 0);
134+ if (r == 0 && pmatch[0].rm_eo == 0) {
135+ /* For example, happens when FS can match
136+ * an empty string (awk -F ' *'). Logically,
137+ * this should split into one-char fields.
138+ * However, gawk 5.0.1 searches for first
139+ * _non-empty_ separator string match:
140+ */
141+ size_t ofs = 0;
142+ do {
143+ ofs++;
144+ if (!s[ofs])
145+ return REG_NOMATCH;
146+ regexec(preg, s + ofs, 1, pmatch, 0);
147+ } while (pmatch[0].rm_eo == 0);
148+ pmatch[0].rm_so += ofs;
149+ pmatch[0].rm_eo += ofs;
150+ }
151+ return r;
152+}
153+
154 static int awk_split(const char *s, node *spl, char **slist)
155 {
156- int l, n;
157+ int n;
158 char c[4];
159 char *s1;
160- regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
161
162 /* in worst case, each char would be a separate field */
163 *slist = s1 = xzalloc(strlen(s) * 2 + 3);
164@@ -1769,29 +1807,31 @@ static int awk_split(const char *s, node *spl, char **slist)
165 return n; /* "": zero fields */
166 n++; /* at least one field will be there */
167 do {
168+ int l;
169+ regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
170+
171 l = strcspn(s, c+2); /* len till next NUL or \n */
172- if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0
173+ if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0
174 && pmatch[0].rm_so <= l
175 ) {
176+ /* if (pmatch[0].rm_eo == 0) ... - impossible */
177 l = pmatch[0].rm_so;
178- if (pmatch[0].rm_eo == 0) {
179- l++;
180- pmatch[0].rm_eo++;
181- }
182 n++; /* we saw yet another delimiter */
183 } else {
184 pmatch[0].rm_eo = l;
185 if (s[l])
186 pmatch[0].rm_eo++;
187 }
188- memcpy(s1, s, l);
189- /* make sure we remove *all* of the separator chars */
190- do {
191- s1[l] = '\0';
192- } while (++l < pmatch[0].rm_eo);
193- nextword(&s1);
194+ s1 = mempcpy(s1, s, l);
195+ *s1++ = '\0';
196 s += pmatch[0].rm_eo;
197 } while (*s);
198+
199+ /* echo a-- | awk -F-- '{ print NF, length($NF), $NF }'
200+ * should print "2 0 ":
201+ */
202+ *s1 = '\0';
203+
204 return n;
205 }
206 if (c[0] == '\0') { /* null split */
207@@ -1995,7 +2035,7 @@ static int ptest(node *pattern)
208 static int awk_getline(rstream *rsm, var *v)
209 {
210 char *b;
211- regmatch_t pmatch[2];
212+ regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
213 int size, a, p, pp = 0;
214 int fd, so, eo, r, rp;
215 char c, *m, *s;
diff --git a/meta/recipes-core/coreutils/coreutils_8.31.bb b/meta/recipes-core/coreutils/coreutils_8.31.bb
index 7dd9e41def..3841f71155 100644
--- a/meta/recipes-core/coreutils/coreutils_8.31.bb
+++ b/meta/recipes-core/coreutils/coreutils_8.31.bb
@@ -26,6 +26,10 @@ SRC_URI_append_libc-musl = "file://strtod_fix_clash_with_strtold.patch"
26SRC_URI[md5sum] = "0009a224d8e288e8ec406ef0161f9293" 26SRC_URI[md5sum] = "0009a224d8e288e8ec406ef0161f9293"
27SRC_URI[sha256sum] = "ff7a9c918edce6b4f4b2725e3f9b37b0c4d193531cac49a48b56c4d0d3a9e9fd" 27SRC_URI[sha256sum] = "ff7a9c918edce6b4f4b2725e3f9b37b0c4d193531cac49a48b56c4d0d3a9e9fd"
28 28
29# http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=v8.27-101-gf5d7c0842
30# runcon is not really a sandbox command, use `runcon ... setsid ...` to avoid this particular issue.
31CVE_CHECK_WHITELIST += "CVE-2016-2781"
32
29EXTRA_OECONF_class-native = "--without-gmp" 33EXTRA_OECONF_class-native = "--without-gmp"
30EXTRA_OECONF_class-target = "--enable-install-program=arch,hostname --libexecdir=${libdir}" 34EXTRA_OECONF_class-target = "--enable-install-program=arch,hostname --libexecdir=${libdir}"
31EXTRA_OECONF_class-nativesdk = "--enable-install-program=arch,hostname" 35EXTRA_OECONF_class-nativesdk = "--enable-install-program=arch,hostname"
@@ -47,6 +51,7 @@ PACKAGECONFIG_class-nativesdk ??= "xattr"
47PACKAGECONFIG[acl] = "--enable-acl,--disable-acl,acl," 51PACKAGECONFIG[acl] = "--enable-acl,--disable-acl,acl,"
48PACKAGECONFIG[xattr] = "--enable-xattr,--disable-xattr,attr," 52PACKAGECONFIG[xattr] = "--enable-xattr,--disable-xattr,attr,"
49PACKAGECONFIG[single-binary] = "--enable-single-binary,--disable-single-binary,," 53PACKAGECONFIG[single-binary] = "--enable-single-binary,--disable-single-binary,,"
54PACKAGECONFIG[openssl] = "--with-openssl=yes,--with-openssl=no,openssl"
50 55
51# [ df mktemp nice printenv base64 gets a special treatment and is not included in this 56# [ df mktemp nice printenv base64 gets a special treatment and is not included in this
52bindir_progs = "arch basename chcon cksum comm csplit cut dir dircolors dirname du \ 57bindir_progs = "arch basename chcon cksum comm csplit cut dir dircolors dirname du \
@@ -202,6 +207,3 @@ do_install_ptest () {
202} 207}
203 208
204FILES_${PN}-ptest += "${bindir}/getlimits" 209FILES_${PN}-ptest += "${bindir}/getlimits"
205
206# These are specific to Opensuse
207CVE_WHITELIST += "CVE-2013-0221 CVE-2013-0222 CVE-2013-0223"
diff --git a/meta/recipes-core/dbus-wait/dbus-wait_git.bb b/meta/recipes-core/dbus-wait/dbus-wait_git.bb
index c24295b537..b39f7523c0 100644
--- a/meta/recipes-core/dbus-wait/dbus-wait_git.bb
+++ b/meta/recipes-core/dbus-wait/dbus-wait_git.bb
@@ -1,5 +1,6 @@
1SUMMARY = "A simple tool to wait for a specific signal over DBus" 1SUMMARY = "A simple tool to wait for a specific signal over DBus"
2HOMEPAGE = "http://git.yoctoproject.org/cgit/cgit.cgi/dbus-wait" 2HOMEPAGE = "http://git.yoctoproject.org/cgit/cgit.cgi/dbus-wait"
3DESCRIPTION = "${SUMMARY}"
3SECTION = "base" 4SECTION = "base"
4LICENSE = "GPLv2" 5LICENSE = "GPLv2"
5LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263" 6LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
@@ -10,7 +11,7 @@ SRCREV = "6cc6077a36fe2648a5f993fe7c16c9632f946517"
10PV = "0.1+git${SRCPV}" 11PV = "0.1+git${SRCPV}"
11PR = "r2" 12PR = "r2"
12 13
13SRC_URI = "git://git.yoctoproject.org/${BPN}" 14SRC_URI = "git://git.yoctoproject.org/${BPN};branch=master"
14UPSTREAM_CHECK_COMMITS = "1" 15UPSTREAM_CHECK_COMMITS = "1"
15 16
16S = "${WORKDIR}/git" 17S = "${WORKDIR}/git"
diff --git a/meta/recipes-core/dbus/dbus-test_1.12.16.bb b/meta/recipes-core/dbus/dbus-test_1.12.24.bb
index bea0e74ed0..755c841bad 100644
--- a/meta/recipes-core/dbus/dbus-test_1.12.16.bb
+++ b/meta/recipes-core/dbus/dbus-test_1.12.24.bb
@@ -1,57 +1,31 @@
1SUMMARY = "D-Bus test package (for D-bus functionality testing only)" 1SUMMARY = "D-Bus test package (for D-bus functionality testing only)"
2HOMEPAGE = "http://dbus.freedesktop.org" 2HOMEPAGE = "http://dbus.freedesktop.org"
3SECTION = "base" 3SECTION = "base"
4LICENSE = "AFL-2.1 | GPLv2+"
5LIC_FILES_CHKSUM = "file://COPYING;md5=10dded3b58148f3f1fd804b26354af3e \
6 file://dbus/dbus.h;beginline=6;endline=20;md5=7755c9d7abccd5dbd25a6a974538bb3c"
7 4
8DEPENDS = "dbus glib-2.0" 5require dbus.inc
9 6
10RDEPENDS_${PN}-dev = "" 7SRC_URI += "file://run-ptest \
8 file://python-config.patch \
9 "
11 10
12SRC_URI = "http://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \ 11DEPENDS = "dbus glib-2.0"
13 file://tmpdir.patch \
14 file://run-ptest \
15 file://python-config.patch \
16 file://clear-guid_from_server-if-send_negotiate_unix_f.patch \
17 "
18 12
19SRC_URI[md5sum] = "2dbeae80dfc9e3632320c6a53d5e8890" 13RDEPENDS_${PN}-dev = ""
20SRC_URI[sha256sum] = "54a22d2fa42f2eb2a871f32811c6005b531b9613b1b93a0d269b05e7549fec80"
21 14
22S="${WORKDIR}/dbus-${PV}" 15S="${WORKDIR}/dbus-${PV}"
23FILESEXTRAPATHS =. "${FILE_DIRNAME}/dbus:" 16FILESEXTRAPATHS =. "${FILE_DIRNAME}/dbus:"
24 17
25inherit autotools pkgconfig gettext ptest upstream-version-is-even 18inherit ptest
26 19
27EXTRA_OECONF_X = "${@bb.utils.contains('DISTRO_FEATURES', 'x11', '--with-x', '--without-x', d)}" 20EXTRA_OECONF += "--enable-tests \
28EXTRA_OECONF_X_class-native = "--without-x"
29
30EXTRA_OECONF = "--enable-tests \
31 --enable-modular-tests \ 21 --enable-modular-tests \
32 --enable-installed-tests \ 22 --enable-installed-tests \
33 --enable-checks \ 23 --enable-checks \
34 --enable-asserts \ 24 --enable-asserts \
35 --enable-largefile \
36 --disable-xml-docs \
37 --disable-doxygen-docs \
38 --disable-libaudit \
39 --with-dbus-test-dir=${PTEST_PATH} \ 25 --with-dbus-test-dir=${PTEST_PATH} \
40 ${EXTRA_OECONF_X} \
41 --enable-embedded-tests \ 26 --enable-embedded-tests \
42 " 27 "
43 28
44EXTRA_OECONF_append_class-target = " SYSTEMCTL=${base_bindir}/systemctl"
45
46PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'systemd x11', d)}"
47PACKAGECONFIG_class-native = ""
48PACKAGECONFIG_class-nativesdk = ""
49
50PACKAGECONFIG[systemd] = "--enable-systemd --with-systemdsystemunitdir=${systemd_system_unitdir},--disable-systemd --without-systemdsystemunitdir,systemd"
51PACKAGECONFIG[x11] = "--with-x --enable-x11-autolaunch,--without-x --disable-x11-autolaunch, virtual/libx11 libsm"
52PACKAGECONFIG[user-session] = "--enable-user-session --with-systemduserunitdir=${systemd_user_unitdir},--disable-user-session"
53PACKAGECONFIG[verbose-mode] = "--enable-verbose-mode,,,"
54
55do_install() { 29do_install() {
56 : 30 :
57} 31}
diff --git a/meta/recipes-core/dbus/dbus.inc b/meta/recipes-core/dbus/dbus.inc
new file mode 100644
index 0000000000..9b5cc53d92
--- /dev/null
+++ b/meta/recipes-core/dbus/dbus.inc
@@ -0,0 +1,36 @@
1inherit autotools pkgconfig gettext upstream-version-is-even
2
3LICENSE = "AFL-2.1 | GPLv2+"
4LIC_FILES_CHKSUM = "file://COPYING;md5=10dded3b58148f3f1fd804b26354af3e \
5 file://dbus/dbus.h;beginline=6;endline=20;md5=7755c9d7abccd5dbd25a6a974538bb3c"
6
7SRC_URI = "https://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \
8 file://tmpdir.patch \
9 file://dbus-1.init \
10 file://clear-guid_from_server-if-send_negotiate_unix_f.patch \
11 file://CVE-2023-34969.patch \
12"
13
14SRC_URI[sha256sum] = "bc42d196c1756ac520d61bf3ccd6f42013617def45dd1e591a6091abf51dca38"
15
16EXTRA_OECONF = "--disable-xml-docs \
17 --disable-doxygen-docs \
18 --disable-libaudit \
19 --enable-largefile \
20 --with-system-socket=/run/dbus/system_bus_socket \
21 "
22EXTRA_OECONF_append_class-target = " SYSTEMCTL=${base_bindir}/systemctl"
23EXTRA_OECONF_append_class-native = " --disable-selinux"
24
25PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'systemd x11', d)} \
26 user-session \
27 "
28PACKAGECONFIG_class-native = ""
29PACKAGECONFIG_class-nativesdk = ""
30
31PACKAGECONFIG[systemd] = "--enable-systemd --with-systemdsystemunitdir=${systemd_system_unitdir},--disable-systemd --without-systemdsystemunitdir,systemd"
32PACKAGECONFIG[x11] = "--with-x --enable-x11-autolaunch,--without-x --disable-x11-autolaunch, virtual/libx11 libsm"
33PACKAGECONFIG[user-session] = "--enable-user-session --with-systemduserunitdir=${systemd_user_unitdir},--disable-user-session"
34PACKAGECONFIG[verbose-mode] = "--enable-verbose-mode,,,"
35
36CVE_PRODUCT += "d-bus_project:d-bus freedesktop:dbus freedesktop:libdbus"
diff --git a/meta/recipes-core/dbus/dbus/CVE-2020-12049.patch b/meta/recipes-core/dbus/dbus/CVE-2020-12049.patch
deleted file mode 100644
index ac7a4b7a71..0000000000
--- a/meta/recipes-core/dbus/dbus/CVE-2020-12049.patch
+++ /dev/null
@@ -1,78 +0,0 @@
1From 872b085f12f56da25a2dbd9bd0b2dff31d5aea63 Mon Sep 17 00:00:00 2001
2From: Simon McVittie <smcv@collabora.com>
3Date: Thu, 16 Apr 2020 14:45:11 +0100
4Subject: [PATCH] sysdeps-unix: On MSG_CTRUNC, close the fds we did receive
5
6MSG_CTRUNC indicates that we have received fewer fds that we should
7have done because the buffer was too small, but we were treating it
8as though it indicated that we received *no* fds. If we received any,
9we still have to make sure we close them, otherwise they will be leaked.
10
11On the system bus, if an attacker can induce us to leak fds in this
12way, that's a local denial of service via resource exhaustion.
13
14Reported-by: Kevin Backhouse, GitHub Security Lab
15Fixes: dbus#294
16Fixes: CVE-2020-12049
17Fixes: GHSL-2020-057
18
19Upstream-Status: Backport [https://gitlab.freedesktop.org/dbus/dbus/-/commit/872b085f12f56da25a2dbd9bd0b2dff31d5aea63]
20CVE: CVE-2020-12049
21Signed-off-by: Lee Chee Yang <chee.yang.lee@intel.com>
22---
23 dbus/dbus-sysdeps-unix.c | 32 ++++++++++++++++++++------------
24 1 file changed, 20 insertions(+), 12 deletions(-)
25
26diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
27index b5fc2466..b176dae1 100644
28--- a/dbus/dbus-sysdeps-unix.c
29+++ b/dbus/dbus-sysdeps-unix.c
30@@ -435,18 +435,6 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
31 struct cmsghdr *cm;
32 dbus_bool_t found = FALSE;
33
34- if (m.msg_flags & MSG_CTRUNC)
35- {
36- /* Hmm, apparently the control data was truncated. The bad
37- thing is that we might have completely lost a couple of fds
38- without chance to recover them. Hence let's treat this as a
39- serious error. */
40-
41- errno = ENOSPC;
42- _dbus_string_set_length (buffer, start);
43- return -1;
44- }
45-
46 for (cm = CMSG_FIRSTHDR(&m); cm; cm = CMSG_NXTHDR(&m, cm))
47 if (cm->cmsg_level == SOL_SOCKET && cm->cmsg_type == SCM_RIGHTS)
48 {
49@@ -501,6 +489,26 @@ _dbus_read_socket_with_unix_fds (DBusSocket fd,
50 if (!found)
51 *n_fds = 0;
52
53+ if (m.msg_flags & MSG_CTRUNC)
54+ {
55+ unsigned int i;
56+
57+ /* Hmm, apparently the control data was truncated. The bad
58+ thing is that we might have completely lost a couple of fds
59+ without chance to recover them. Hence let's treat this as a
60+ serious error. */
61+
62+ /* We still need to close whatever fds we *did* receive,
63+ * otherwise they'll never get closed. (CVE-2020-12049) */
64+ for (i = 0; i < *n_fds; i++)
65+ close (fds[i]);
66+
67+ *n_fds = 0;
68+ errno = ENOSPC;
69+ _dbus_string_set_length (buffer, start);
70+ return -1;
71+ }
72+
73 /* put length back (doesn't actually realloc) */
74 _dbus_string_set_length (buffer, start + bytes_read);
75
76--
772.25.1
78
diff --git a/meta/recipes-core/dbus/dbus/CVE-2023-34969.patch b/meta/recipes-core/dbus/dbus/CVE-2023-34969.patch
new file mode 100644
index 0000000000..8f29185cf6
--- /dev/null
+++ b/meta/recipes-core/dbus/dbus/CVE-2023-34969.patch
@@ -0,0 +1,96 @@
1From 37a4dc5835731a1f7a81f1b67c45b8dfb556dd1c Mon Sep 17 00:00:00 2001
2From: hongjinghao <q1204531485@163.com>
3Date: Mon, 5 Jun 2023 18:17:06 +0100
4Subject: [PATCH] bus: Assign a serial number for messages from the driver
5
6Normally, it's enough to rely on a message being given a serial number
7by the DBusConnection just before it is actually sent. However, in the
8rare case where the policy blocks the driver from sending a message
9(due to a deny rule or the outgoing message quota being full), we need
10to get a valid serial number sooner, so that we can copy it into the
11DBUS_HEADER_FIELD_REPLY_SERIAL field (which is mandatory) in the error
12message sent to monitors. Otherwise, the dbus-daemon will crash with
13an assertion failure if at least one Monitoring client is attached,
14because zero is not a valid serial number to copy.
15
16This fixes a denial-of-service vulnerability: if a privileged user is
17monitoring the well-known system bus using a Monitoring client like
18dbus-monitor or `busctl monitor`, then an unprivileged user can cause
19denial-of-service by triggering this crash. A mitigation for this
20vulnerability is to avoid attaching Monitoring clients to the system
21bus when they are not needed. If there are no Monitoring clients, then
22the vulnerable code is not reached.
23
24Co-authored-by: Simon McVittie <smcv@collabora.com>
25Resolves: dbus/dbus#457
26(cherry picked from commit b159849e031000d1dbc1ab876b5fc78a3ce9b534)
27---
28 bus/connection.c | 15 +++++++++++++++
29 dbus/dbus-connection-internal.h | 2 ++
30 dbus/dbus-connection.c | 11 ++++++++++-
31 3 files changed, 27 insertions(+), 1 deletion(-)
32
33diff --git a/bus/connection.c b/bus/connection.c
34index b3583433..215f0230 100644
35--- a/bus/connection.c
36+++ b/bus/connection.c
37@@ -2350,6 +2350,21 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
38 if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
39 return FALSE;
40
41+ /* Make sure the message has a non-zero serial number, otherwise
42+ * bus_transaction_capture_error_reply() will not be able to mock up
43+ * a corresponding reply for it. Normally this would be delayed until
44+ * the first time we actually send the message out from a
45+ * connection, when the transaction is committed, but that's too late
46+ * in this case.
47+ */
48+ if (dbus_message_get_serial (message) == 0)
49+ {
50+ dbus_uint32_t next_serial;
51+
52+ next_serial = _dbus_connection_get_next_client_serial (connection);
53+ dbus_message_set_serial (message, next_serial);
54+ }
55+
56 if (bus_connection_is_active (connection))
57 {
58 if (!dbus_message_set_destination (message,
59diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
60index 48357321..ba79b192 100644
61--- a/dbus/dbus-connection-internal.h
62+++ b/dbus/dbus-connection-internal.h
63@@ -54,6 +54,8 @@ DBUS_PRIVATE_EXPORT
64 DBusConnection * _dbus_connection_ref_unlocked (DBusConnection *connection);
65 DBUS_PRIVATE_EXPORT
66 void _dbus_connection_unref_unlocked (DBusConnection *connection);
67+DBUS_PRIVATE_EXPORT
68+dbus_uint32_t _dbus_connection_get_next_client_serial (DBusConnection *connection);
69 void _dbus_connection_queue_received_message_link (DBusConnection *connection,
70 DBusList *link);
71 dbus_bool_t _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection);
72diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
73index c525b6dc..09cef278 100644
74--- a/dbus/dbus-connection.c
75+++ b/dbus/dbus-connection.c
76@@ -1456,7 +1456,16 @@ _dbus_connection_unref_unlocked (DBusConnection *connection)
77 _dbus_connection_last_unref (connection);
78 }
79
80-static dbus_uint32_t
81+/**
82+ * Allocate and return the next non-zero serial number for outgoing messages.
83+ *
84+ * This method is only valid to call from single-threaded code, such as
85+ * the dbus-daemon, or with the connection lock held.
86+ *
87+ * @param connection the connection
88+ * @returns A suitable serial number for the next message to be sent on the connection.
89+ */
90+dbus_uint32_t
91 _dbus_connection_get_next_client_serial (DBusConnection *connection)
92 {
93 dbus_uint32_t serial;
94--
952.25.1
96
diff --git a/meta/recipes-core/dbus/dbus_1.12.16.bb b/meta/recipes-core/dbus/dbus_1.12.24.bb
index 10d1b34448..cf6f7dc0ef 100644
--- a/meta/recipes-core/dbus/dbus_1.12.16.bb
+++ b/meta/recipes-core/dbus/dbus_1.12.24.bb
@@ -2,9 +2,9 @@ SUMMARY = "D-Bus message bus"
2DESCRIPTION = "D-Bus is a message bus system, a simple way for applications to talk to one another. In addition to interprocess communication, D-Bus helps coordinate process lifecycle; it makes it simple and reliable to code a \"single instance\" application or daemon, and to launch applications and daemons on demand when their services are needed." 2DESCRIPTION = "D-Bus is a message bus system, a simple way for applications to talk to one another. In addition to interprocess communication, D-Bus helps coordinate process lifecycle; it makes it simple and reliable to code a \"single instance\" application or daemon, and to launch applications and daemons on demand when their services are needed."
3HOMEPAGE = "https://dbus.freedesktop.org" 3HOMEPAGE = "https://dbus.freedesktop.org"
4SECTION = "base" 4SECTION = "base"
5LICENSE = "AFL-2.1 | GPLv2+" 5
6LIC_FILES_CHKSUM = "file://COPYING;md5=10dded3b58148f3f1fd804b26354af3e \ 6require dbus.inc
7 file://dbus/dbus.h;beginline=6;endline=20;md5=7755c9d7abccd5dbd25a6a974538bb3c" 7
8DEPENDS = "expat virtual/libintl autoconf-archive" 8DEPENDS = "expat virtual/libintl autoconf-archive"
9RDEPENDS_dbus_class-native = "" 9RDEPENDS_dbus_class-native = ""
10RDEPENDS_dbus_class-nativesdk = "" 10RDEPENDS_dbus_class-nativesdk = ""
@@ -12,17 +12,7 @@ PACKAGES += "${@bb.utils.contains('DISTRO_FEATURES', 'ptest', '${PN}-ptest', '',
12ALLOW_EMPTY_dbus-ptest = "1" 12ALLOW_EMPTY_dbus-ptest = "1"
13RDEPENDS_dbus-ptest_class-target = "dbus-test-ptest" 13RDEPENDS_dbus-ptest_class-target = "dbus-test-ptest"
14 14
15SRC_URI = "https://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \ 15inherit useradd update-rc.d
16 file://tmpdir.patch \
17 file://dbus-1.init \
18 file://clear-guid_from_server-if-send_negotiate_unix_f.patch \
19 file://CVE-2020-12049.patch \
20"
21
22SRC_URI[md5sum] = "2dbeae80dfc9e3632320c6a53d5e8890"
23SRC_URI[sha256sum] = "54a22d2fa42f2eb2a871f32811c6005b531b9613b1b93a0d269b05e7549fec80"
24
25inherit useradd autotools pkgconfig gettext update-rc.d upstream-version-is-even
26 16
27INITSCRIPT_NAME = "dbus-1" 17INITSCRIPT_NAME = "dbus-1"
28INITSCRIPT_PARAMS = "start 02 5 3 2 . stop 20 0 1 6 ." 18INITSCRIPT_PARAMS = "start 02 5 3 2 . stop 20 0 1 6 ."
@@ -93,27 +83,7 @@ pkg_postinst_dbus() {
93} 83}
94 84
95 85
96EXTRA_OECONF = "--disable-tests \ 86EXTRA_OECONF += "--disable-tests"
97 --disable-xml-docs \
98 --disable-doxygen-docs \
99 --disable-libaudit \
100 --enable-largefile \
101 --with-system-socket=/run/dbus/system_bus_socket \
102 "
103
104EXTRA_OECONF_append_class-target = " SYSTEMCTL=${base_bindir}/systemctl"
105EXTRA_OECONF_append_class-native = " --disable-selinux"
106
107PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'systemd x11', d)} \
108 user-session \
109 "
110
111PACKAGECONFIG_class-native = ""
112PACKAGECONFIG_class-nativesdk = ""
113
114PACKAGECONFIG[systemd] = "--enable-systemd --with-systemdsystemunitdir=${systemd_system_unitdir},--disable-systemd --without-systemdsystemunitdir,systemd"
115PACKAGECONFIG[x11] = "--with-x --enable-x11-autolaunch,--without-x --disable-x11-autolaunch, virtual/libx11 libsm"
116PACKAGECONFIG[user-session] = "--enable-user-session --with-systemduserunitdir=${systemd_user_unitdir},--disable-user-session"
117 87
118do_install() { 88do_install() {
119 autotools_do_install 89 autotools_do_install
diff --git a/meta/recipes-core/dropbear/dropbear.inc b/meta/recipes-core/dropbear/dropbear.inc
index 7269888a4e..0f5e9ba4ac 100644
--- a/meta/recipes-core/dropbear/dropbear.inc
+++ b/meta/recipes-core/dropbear/dropbear.inc
@@ -1,5 +1,6 @@
1SUMMARY = "A lightweight SSH and SCP implementation" 1SUMMARY = "A lightweight SSH and SCP implementation"
2HOMEPAGE = "http://matt.ucc.asn.au/dropbear/dropbear.html" 2HOMEPAGE = "http://matt.ucc.asn.au/dropbear/dropbear.html"
3DESCRIPTION = "Dropbear is a relatively small SSH server and client. It runs on a variety of POSIX-based platforms. Dropbear is open source software, distributed under a MIT-style license. Dropbear is particularly useful for "embedded"-type Linux (or other Unix) systems, such as wireless routers."
3SECTION = "console/network" 4SECTION = "console/network"
4 5
5# some files are from other projects and have others license terms: 6# some files are from other projects and have others license terms:
@@ -11,6 +12,11 @@ DEPENDS = "zlib virtual/crypt"
11RPROVIDES_${PN} = "ssh sshd" 12RPROVIDES_${PN} = "ssh sshd"
12RCONFLICTS_${PN} = "openssh-sshd openssh" 13RCONFLICTS_${PN} = "openssh-sshd openssh"
13 14
15# break dependency on base package for -dev package
16# otherwise SDK fails to build as the main openssh and dropbear packages
17# conflict with each other
18RDEPENDS:${PN}-dev = ""
19
14DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'pam', 'libpam', '', d)}" 20DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'pam', 'libpam', '', d)}"
15 21
16SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \ 22SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \
@@ -21,7 +27,10 @@ SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \
21 file://dropbear.socket \ 27 file://dropbear.socket \
22 file://dropbear.default \ 28 file://dropbear.default \
23 ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \ 29 ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \
24 ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} " 30 ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} \
31 file://CVE-2020-36254.patch \
32 file://CVE-2021-36369.patch \
33 "
25 34
26PAM_SRC_URI = "file://0005-dropbear-enable-pam.patch \ 35PAM_SRC_URI = "file://0005-dropbear-enable-pam.patch \
27 file://0006-dropbear-configuration-file.patch \ 36 file://0006-dropbear-configuration-file.patch \
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2020-36254.patch b/meta/recipes-core/dropbear/dropbear/CVE-2020-36254.patch
new file mode 100644
index 0000000000..64d0d96486
--- /dev/null
+++ b/meta/recipes-core/dropbear/dropbear/CVE-2020-36254.patch
@@ -0,0 +1,29 @@
1From c96c48d62aefc372f2105293ddf8cff2d116dc3a Mon Sep 17 00:00:00 2001
2From: Haelwenn Monnier <contact+github.com@hacktivis.me>
3Date: Mon, 25 May 2020 14:54:29 +0200
4Subject: [PATCH] scp.c: Port OpenSSH CVE-2018-20685 fix (#80)
5
6Reference:
7https://github.com/mkj/dropbear/commit/8f8a3dff705fad774a10864a2e3dbcfa9779ceff
8
9CVE: CVE-2020-36254
10Upstream-Status: Backport
11
12---
13 scp.c | 3 ++-
14 1 file changed, 2 insertions(+), 1 deletion(-)
15
16diff --git a/scp.c b/scp.c
17index 742ae00..7b8e7d2 100644
18--- a/scp.c
19+++ b/scp.c
20@@ -935,7 +935,8 @@ sink(int argc, char **argv)
21 size = size * 10 + (*cp++ - '0');
22 if (*cp++ != ' ')
23 SCREWUP("size not delimited");
24- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
25+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
26+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
27 run_err("error: unexpected filename: %s", cp);
28 exit(1);
29 }
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2021-36369.patch b/meta/recipes-core/dropbear/dropbear/CVE-2021-36369.patch
new file mode 100644
index 0000000000..5cabe8339d
--- /dev/null
+++ b/meta/recipes-core/dropbear/dropbear/CVE-2021-36369.patch
@@ -0,0 +1,145 @@
1From e10dec82930863e487b22978d3df107274f366b2 Mon Sep 17 00:00:00 2001
2From: Manfred Kaiser <37737811+manfred-kaiser@users.noreply.github.com>
3Date: Thu, 19 Aug 2021 17:37:14 +0200
4Subject: [PATCH] added option to disable trivial auth methods (#128)
5
6* added option to disable trivial auth methods
7
8* rename argument to match with other ssh clients
9
10* fixed trivial auth detection for pubkeys
11
12[https://github.com/mkj/dropbear/pull/128]
13Upstream-Status: Backport
14CVE: CVE-2021-36369
15Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
16
17---
18 cli-auth.c | 3 +++
19 cli-authinteract.c | 1 +
20 cli-authpasswd.c | 2 +-
21 cli-authpubkey.c | 1 +
22 cli-runopts.c | 7 +++++++
23 cli-session.c | 1 +
24 runopts.h | 1 +
25 session.h | 1 +
26 8 files changed, 16 insertions(+), 1 deletion(-)
27
28diff --git a/cli-auth.c b/cli-auth.c
29index 2e509e5..6f04495 100644
30--- a/cli-auth.c
31+++ b/cli-auth.c
32@@ -267,6 +267,9 @@ void recv_msg_userauth_success() {
33 if DROPBEAR_CLI_IMMEDIATE_AUTH is set */
34
35 TRACE(("received msg_userauth_success"))
36+ if (cli_opts.disable_trivial_auth && cli_ses.is_trivial_auth) {
37+ dropbear_exit("trivial authentication not allowed");
38+ }
39 /* Note: in delayed-zlib mode, setting authdone here
40 * will enable compression in the transport layer */
41 ses.authstate.authdone = 1;
42diff --git a/cli-authinteract.c b/cli-authinteract.c
43index e1cc9a1..f7128ee 100644
44--- a/cli-authinteract.c
45+++ b/cli-authinteract.c
46@@ -114,6 +114,7 @@ void recv_msg_userauth_info_request() {
47 m_free(instruction);
48
49 for (i = 0; i < num_prompts; i++) {
50+ cli_ses.is_trivial_auth = 0;
51 unsigned int response_len = 0;
52 prompt = buf_getstring(ses.payload, NULL);
53 cleantext(prompt);
54diff --git a/cli-authpasswd.c b/cli-authpasswd.c
55index 00fdd8b..a24d43e 100644
56--- a/cli-authpasswd.c
57+++ b/cli-authpasswd.c
58@@ -155,7 +155,7 @@ void cli_auth_password() {
59
60 encrypt_packet();
61 m_burn(password, strlen(password));
62-
63+ cli_ses.is_trivial_auth = 0;
64 TRACE(("leave cli_auth_password"))
65 }
66 #endif /* DROPBEAR_CLI_PASSWORD_AUTH */
67diff --git a/cli-authpubkey.c b/cli-authpubkey.c
68index 7cee164..7da1a04 100644
69--- a/cli-authpubkey.c
70+++ b/cli-authpubkey.c
71@@ -174,6 +174,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
72 buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
73 cli_buf_put_sign(ses.writepayload, key, type, sigbuf);
74 buf_free(sigbuf); /* Nothing confidential in the buffer */
75+ cli_ses.is_trivial_auth = 0;
76 }
77
78 encrypt_packet();
79diff --git a/cli-runopts.c b/cli-runopts.c
80index 7d1fffe..6bf8b8e 100644
81--- a/cli-runopts.c
82+++ b/cli-runopts.c
83@@ -152,6 +152,7 @@ void cli_getopts(int argc, char ** argv) {
84 #if DROPBEAR_CLI_ANYTCPFWD
85 cli_opts.exit_on_fwd_failure = 0;
86 #endif
87+ cli_opts.disable_trivial_auth = 0;
88 #if DROPBEAR_CLI_LOCALTCPFWD
89 cli_opts.localfwds = list_new();
90 opts.listen_fwd_all = 0;
91@@ -888,6 +889,7 @@ static void add_extendedopt(const char* origstr) {
92 #if DROPBEAR_CLI_ANYTCPFWD
93 "\tExitOnForwardFailure\n"
94 #endif
95+ "\tDisableTrivialAuth\n"
96 #ifndef DISABLE_SYSLOG
97 "\tUseSyslog\n"
98 #endif
99@@ -915,5 +917,10 @@ static void add_extendedopt(const char* origstr) {
100 return;
101 }
102
103+ if (match_extendedopt(&optstr, "DisableTrivialAuth") == DROPBEAR_SUCCESS) {
104+ cli_opts.disable_trivial_auth = parse_flag_value(optstr);
105+ return;
106+ }
107+
108 dropbear_log(LOG_WARNING, "Ignoring unknown configuration option '%s'", origstr);
109 }
110diff --git a/cli-session.c b/cli-session.c
111index 56dd4af..73ef0db 100644
112--- a/cli-session.c
113+++ b/cli-session.c
114@@ -164,6 +164,7 @@ static void cli_session_init(pid_t proxy_cmd_pid) {
115 /* Auth */
116 cli_ses.lastprivkey = NULL;
117 cli_ses.lastauthtype = 0;
118+ cli_ses.is_trivial_auth = 1;
119
120 /* For printing "remote host closed" for the user */
121 ses.remoteclosed = cli_remoteclosed;
122diff --git a/runopts.h b/runopts.h
123index 31eae1f..8519626 100644
124--- a/runopts.h
125+++ b/runopts.h
126@@ -154,6 +154,7 @@ typedef struct cli_runopts {
127 #if DROPBEAR_CLI_ANYTCPFWD
128 int exit_on_fwd_failure;
129 #endif
130+ int disable_trivial_auth;
131 #if DROPBEAR_CLI_REMOTETCPFWD
132 m_list * remotefwds;
133 #endif
134diff --git a/session.h b/session.h
135index 0f77055..8676054 100644
136--- a/session.h
137+++ b/session.h
138@@ -287,6 +287,7 @@ struct clientsession {
139
140 int lastauthtype; /* either AUTH_TYPE_PUBKEY or AUTH_TYPE_PASSWORD,
141 for the last type of auth we tried */
142+ int is_trivial_auth;
143 int ignore_next_auth_response;
144 #if DROPBEAR_CLI_INTERACT_AUTH
145 int auth_interact_failed; /* flag whether interactive auth can still
diff --git a/meta/recipes-core/ell/ell_0.33.bb b/meta/recipes-core/ell/ell_0.33.bb
index 2fa05104fb..bef1e9a0b5 100644
--- a/meta/recipes-core/ell/ell_0.33.bb
+++ b/meta/recipes-core/ell/ell_0.33.bb
@@ -1,4 +1,5 @@
1SUMMARY = "Embedded Linux Library" 1SUMMARY = "Embedded Linux Library"
2HOMEPAGE = "https://01.org/ell"
2DESCRIPTION = "The Embedded Linux Library (ELL) provides core, \ 3DESCRIPTION = "The Embedded Linux Library (ELL) provides core, \
3low-level functionality for system daemons. It typically has no \ 4low-level functionality for system daemons. It typically has no \
4dependencies other than the Linux kernel, C standard library, and \ 5dependencies other than the Linux kernel, C standard library, and \
diff --git a/meta/recipes-core/expat/expat/CVE-2013-0340.patch b/meta/recipes-core/expat/expat/CVE-2013-0340.patch
new file mode 100644
index 0000000000..1ab4d06508
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2013-0340.patch
@@ -0,0 +1,1758 @@
1From a644ccf25392523b1329872310e24d0fc5f40629 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Mon, 19 Apr 2021 21:42:51 +0200
4Subject: [PATCH] expat: Backport fix for CVE-2013-0340
5
6Issue: https://github.com/libexpat/libexpat/issues/34
7
8This patch cherry-picks the following commits from upstream release
92.4.0 onto 2.2.9:
10
11- b1d039607d3d8a042bf0466bfcc1c0f104e353c8
12- 60959f2b491876199879d97c8ed956eabb0c2e73
13
14Upstream-Status: Backport
15CVE: CVE-2013-0340
16Signed-off-by: Jasper Orschulko <jasper@fancydomain.eu>
17---
18 lib/expat.h | 21 +-
19 lib/internal.h | 30 +
20 lib/libexpat.def | 3 +
21 lib/libexpatw.def | 3 +
22 lib/xmlparse.c | 1147 +++++++++++++++++++++++++++++++++++++--
23 5 files changed, 1143 insertions(+), 61 deletions(-)
24
25diff --git a/lib/expat.h b/lib/expat.h
26index 48a6e2a3..0fb70d9d 100644
27--- a/lib/expat.h
28+++ b/lib/expat.h
29@@ -115,7 +115,9 @@ enum XML_Error {
30 XML_ERROR_RESERVED_PREFIX_XMLNS,
31 XML_ERROR_RESERVED_NAMESPACE_URI,
32 /* Added in 2.2.1. */
33- XML_ERROR_INVALID_ARGUMENT
34+ XML_ERROR_INVALID_ARGUMENT,
35+ /* Added in 2.4.0. */
36+ XML_ERROR_AMPLIFICATION_LIMIT_BREACH
37 };
38
39 enum XML_Content_Type {
40@@ -997,7 +999,10 @@ enum XML_FeatureEnum {
41 XML_FEATURE_SIZEOF_XML_LCHAR,
42 XML_FEATURE_NS,
43 XML_FEATURE_LARGE_SIZE,
44- XML_FEATURE_ATTR_INFO
45+ XML_FEATURE_ATTR_INFO,
46+ /* Added in Expat 2.4.0. */
47+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
48+ XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT
49 /* Additional features must be added to the end of this enum. */
50 };
51
52@@ -1010,6 +1015,18 @@ typedef struct {
53 XMLPARSEAPI(const XML_Feature *)
54 XML_GetFeatureList(void);
55
56+#ifdef XML_DTD
57+/* Added in Expat 2.4.0. */
58+XMLPARSEAPI(XML_Bool)
59+XML_SetBillionLaughsAttackProtectionMaximumAmplification(
60+ XML_Parser parser, float maximumAmplificationFactor);
61+
62+/* Added in Expat 2.4.0. */
63+XMLPARSEAPI(XML_Bool)
64+XML_SetBillionLaughsAttackProtectionActivationThreshold(
65+ XML_Parser parser, unsigned long long activationThresholdBytes);
66+#endif
67+
68 /* Expat follows the semantic versioning convention.
69 See http://semver.org.
70 */
71diff --git a/lib/internal.h b/lib/internal.h
72index 60913dab..d8b31fa2 100644
73--- a/lib/internal.h
74+++ b/lib/internal.h
75@@ -101,10 +101,40 @@
76 # endif
77 #endif
78
79+#include <limits.h> // ULONG_MAX
80+
81+#if defined(_WIN32) && ! defined(__USE_MINGW_ANSI_STDIO)
82+# define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
83+# if defined(_WIN64) // Note: modifier "td" does not work for MinGW
84+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
85+# else
86+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
87+# endif
88+#else
89+# define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
90+# if ! defined(ULONG_MAX)
91+# error Compiler did not define ULONG_MAX for us
92+# elif ULONG_MAX == 18446744073709551615u // 2^64-1
93+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
94+# else
95+# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
96+# endif
97+#endif
98+
99 #ifndef UNUSED_P
100 # define UNUSED_P(p) (void)p
101 #endif
102
103+/* NOTE BEGIN If you ever patch these defaults to greater values
104+ for non-attack XML payload in your environment,
105+ please file a bug report with libexpat. Thank you!
106+*/
107+#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT \
108+ 100.0f
109+#define EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT \
110+ 8388608 // 8 MiB, 2^23
111+/* NOTE END */
112+
113 #ifdef __cplusplus
114 extern "C" {
115 #endif
116diff --git a/lib/libexpat.def b/lib/libexpat.def
117index 16faf595..5aefa6df 100644
118--- a/lib/libexpat.def
119+++ b/lib/libexpat.def
120@@ -76,3 +76,6 @@ EXPORTS
121 XML_SetHashSalt @67
122 ; added with version 2.2.5
123 _INTERNAL_trim_to_complete_utf8_characters @68
124+; added with version 2.4.0
125+ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
126+ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
127diff --git a/lib/libexpatw.def b/lib/libexpatw.def
128index 16faf595..5aefa6df 100644
129--- a/lib/libexpatw.def
130+++ b/lib/libexpatw.def
131@@ -76,3 +76,6 @@ EXPORTS
132 XML_SetHashSalt @67
133 ; added with version 2.2.5
134 _INTERNAL_trim_to_complete_utf8_characters @68
135+; added with version 2.4.0
136+ XML_SetBillionLaughsAttackProtectionActivationThreshold @69
137+ XML_SetBillionLaughsAttackProtectionMaximumAmplification @70
138diff --git a/lib/xmlparse.c b/lib/xmlparse.c
139index 3aaf35b9..6790bc28 100644
140--- a/lib/xmlparse.c
141+++ b/lib/xmlparse.c
142@@ -47,6 +47,8 @@
143 #include <limits.h> /* UINT_MAX */
144 #include <stdio.h> /* fprintf */
145 #include <stdlib.h> /* getenv, rand_s */
146+#include <stdint.h> /* uintptr_t */
147+#include <math.h> /* isnan */
148
149 #ifdef _WIN32
150 # define getpid GetCurrentProcessId
151@@ -373,6 +375,31 @@ typedef struct open_internal_entity {
152 XML_Bool betweenDecl; /* WFC: PE Between Declarations */
153 } OPEN_INTERNAL_ENTITY;
154
155+enum XML_Account {
156+ XML_ACCOUNT_DIRECT, /* bytes directly passed to the Expat parser */
157+ XML_ACCOUNT_ENTITY_EXPANSION, /* intermediate bytes produced during entity
158+ expansion */
159+ XML_ACCOUNT_NONE /* i.e. do not account, was accounted already */
160+};
161+
162+#ifdef XML_DTD
163+typedef unsigned long long XmlBigCount;
164+typedef struct accounting {
165+ XmlBigCount countBytesDirect;
166+ XmlBigCount countBytesIndirect;
167+ int debugLevel;
168+ float maximumAmplificationFactor; // >=1.0
169+ unsigned long long activationThresholdBytes;
170+} ACCOUNTING;
171+
172+typedef struct entity_stats {
173+ unsigned int countEverOpened;
174+ unsigned int currentDepth;
175+ unsigned int maximumDepthSeen;
176+ int debugLevel;
177+} ENTITY_STATS;
178+#endif /* XML_DTD */
179+
180 typedef enum XML_Error PTRCALL Processor(XML_Parser parser, const char *start,
181 const char *end, const char **endPtr);
182
183@@ -403,16 +430,18 @@ static enum XML_Error initializeEncoding(XML_Parser parser);
184 static enum XML_Error doProlog(XML_Parser parser, const ENCODING *enc,
185 const char *s, const char *end, int tok,
186 const char *next, const char **nextPtr,
187- XML_Bool haveMore, XML_Bool allowClosingDoctype);
188+ XML_Bool haveMore, XML_Bool allowClosingDoctype,
189+ enum XML_Account account);
190 static enum XML_Error processInternalEntity(XML_Parser parser, ENTITY *entity,
191 XML_Bool betweenDecl);
192 static enum XML_Error doContent(XML_Parser parser, int startTagLevel,
193 const ENCODING *enc, const char *start,
194 const char *end, const char **endPtr,
195- XML_Bool haveMore);
196+ XML_Bool haveMore, enum XML_Account account);
197 static enum XML_Error doCdataSection(XML_Parser parser, const ENCODING *,
198 const char **startPtr, const char *end,
199- const char **nextPtr, XML_Bool haveMore);
200+ const char **nextPtr, XML_Bool haveMore,
201+ enum XML_Account account);
202 #ifdef XML_DTD
203 static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
204 const char **startPtr, const char *end,
205@@ -422,7 +451,8 @@ static enum XML_Error doIgnoreSection(XML_Parser parser, const ENCODING *,
206 static void freeBindings(XML_Parser parser, BINDING *bindings);
207 static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *,
208 const char *s, TAG_NAME *tagNamePtr,
209- BINDING **bindingsPtr);
210+ BINDING **bindingsPtr,
211+ enum XML_Account account);
212 static enum XML_Error addBinding(XML_Parser parser, PREFIX *prefix,
213 const ATTRIBUTE_ID *attId, const XML_Char *uri,
214 BINDING **bindingsPtr);
215@@ -431,15 +461,18 @@ static int defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *, XML_Bool isCdata,
216 XML_Parser parser);
217 static enum XML_Error storeAttributeValue(XML_Parser parser, const ENCODING *,
218 XML_Bool isCdata, const char *,
219- const char *, STRING_POOL *);
220+ const char *, STRING_POOL *,
221+ enum XML_Account account);
222 static enum XML_Error appendAttributeValue(XML_Parser parser, const ENCODING *,
223 XML_Bool isCdata, const char *,
224- const char *, STRING_POOL *);
225+ const char *, STRING_POOL *,
226+ enum XML_Account account);
227 static ATTRIBUTE_ID *getAttributeId(XML_Parser parser, const ENCODING *enc,
228 const char *start, const char *end);
229 static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
230 static enum XML_Error storeEntityValue(XML_Parser parser, const ENCODING *enc,
231- const char *start, const char *end);
232+ const char *start, const char *end,
233+ enum XML_Account account);
234 static int reportProcessingInstruction(XML_Parser parser, const ENCODING *enc,
235 const char *start, const char *end);
236 static int reportComment(XML_Parser parser, const ENCODING *enc,
237@@ -503,6 +536,35 @@ static XML_Parser parserCreate(const XML_Char *encodingName,
238
239 static void parserInit(XML_Parser parser, const XML_Char *encodingName);
240
241+#ifdef XML_DTD
242+static float accountingGetCurrentAmplification(XML_Parser rootParser);
243+static void accountingReportStats(XML_Parser originParser, const char *epilog);
244+static void accountingOnAbort(XML_Parser originParser);
245+static void accountingReportDiff(XML_Parser rootParser,
246+ unsigned int levelsAwayFromRootParser,
247+ const char *before, const char *after,
248+ ptrdiff_t bytesMore, int source_line,
249+ enum XML_Account account);
250+static XML_Bool accountingDiffTolerated(XML_Parser originParser, int tok,
251+ const char *before, const char *after,
252+ int source_line,
253+ enum XML_Account account);
254+
255+static void entityTrackingReportStats(XML_Parser parser, ENTITY *entity,
256+ const char *action, int sourceLine);
257+static void entityTrackingOnOpen(XML_Parser parser, ENTITY *entity,
258+ int sourceLine);
259+static void entityTrackingOnClose(XML_Parser parser, ENTITY *entity,
260+ int sourceLine);
261+
262+static XML_Parser getRootParserOf(XML_Parser parser,
263+ unsigned int *outLevelDiff);
264+static const char *unsignedCharToPrintable(unsigned char c);
265+#endif /* XML_DTD */
266+
267+static unsigned long getDebugLevel(const char *variableName,
268+ unsigned long defaultDebugLevel);
269+
270 #define poolStart(pool) ((pool)->start)
271 #define poolEnd(pool) ((pool)->ptr)
272 #define poolLength(pool) ((pool)->ptr - (pool)->start)
273@@ -616,6 +678,10 @@ struct XML_ParserStruct {
274 enum XML_ParamEntityParsing m_paramEntityParsing;
275 #endif
276 unsigned long m_hash_secret_salt;
277+#ifdef XML_DTD
278+ ACCOUNTING m_accounting;
279+ ENTITY_STATS m_entity_stats;
280+#endif
281 };
282
283 #define MALLOC(parser, s) (parser->m_mem.malloc_fcn((s)))
284@@ -1055,6 +1121,18 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
285 parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
286 #endif
287 parser->m_hash_secret_salt = 0;
288+
289+#ifdef XML_DTD
290+ memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
291+ parser->m_accounting.debugLevel = getDebugLevel("EXPAT_ACCOUNTING_DEBUG", 0u);
292+ parser->m_accounting.maximumAmplificationFactor
293+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT;
294+ parser->m_accounting.activationThresholdBytes
295+ = EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT;
296+
297+ memset(&parser->m_entity_stats, 0, sizeof(ENTITY_STATS));
298+ parser->m_entity_stats.debugLevel = getDebugLevel("EXPAT_ENTITY_DEBUG", 0u);
299+#endif
300 }
301
302 /* moves list of bindings to m_freeBindingList */
303@@ -2318,6 +2396,10 @@ XML_ErrorString(enum XML_Error code) {
304 /* Added in 2.2.5. */
305 case XML_ERROR_INVALID_ARGUMENT: /* Constant added in 2.2.1, already */
306 return XML_L("invalid argument");
307+ /* Added in 2.4.0. */
308+ case XML_ERROR_AMPLIFICATION_LIMIT_BREACH:
309+ return XML_L(
310+ "limit on input amplification factor (from DTD and entities) breached");
311 }
312 return NULL;
313 }
314@@ -2354,41 +2436,75 @@ XML_ExpatVersionInfo(void) {
315
316 const XML_Feature *XMLCALL
317 XML_GetFeatureList(void) {
318- static const XML_Feature features[]
319- = {{XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
320- sizeof(XML_Char)},
321- {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
322- sizeof(XML_LChar)},
323+ static const XML_Feature features[] = {
324+ {XML_FEATURE_SIZEOF_XML_CHAR, XML_L("sizeof(XML_Char)"),
325+ sizeof(XML_Char)},
326+ {XML_FEATURE_SIZEOF_XML_LCHAR, XML_L("sizeof(XML_LChar)"),
327+ sizeof(XML_LChar)},
328 #ifdef XML_UNICODE
329- {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
330+ {XML_FEATURE_UNICODE, XML_L("XML_UNICODE"), 0},
331 #endif
332 #ifdef XML_UNICODE_WCHAR_T
333- {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
334+ {XML_FEATURE_UNICODE_WCHAR_T, XML_L("XML_UNICODE_WCHAR_T"), 0},
335 #endif
336 #ifdef XML_DTD
337- {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
338+ {XML_FEATURE_DTD, XML_L("XML_DTD"), 0},
339 #endif
340 #ifdef XML_CONTEXT_BYTES
341- {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
342- XML_CONTEXT_BYTES},
343+ {XML_FEATURE_CONTEXT_BYTES, XML_L("XML_CONTEXT_BYTES"),
344+ XML_CONTEXT_BYTES},
345 #endif
346 #ifdef XML_MIN_SIZE
347- {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
348+ {XML_FEATURE_MIN_SIZE, XML_L("XML_MIN_SIZE"), 0},
349 #endif
350 #ifdef XML_NS
351- {XML_FEATURE_NS, XML_L("XML_NS"), 0},
352+ {XML_FEATURE_NS, XML_L("XML_NS"), 0},
353 #endif
354 #ifdef XML_LARGE_SIZE
355- {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
356+ {XML_FEATURE_LARGE_SIZE, XML_L("XML_LARGE_SIZE"), 0},
357 #endif
358 #ifdef XML_ATTR_INFO
359- {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
360+ {XML_FEATURE_ATTR_INFO, XML_L("XML_ATTR_INFO"), 0},
361 #endif
362- {XML_FEATURE_END, NULL, 0}};
363+#ifdef XML_DTD
364+ /* Added in Expat 2.4.0. */
365+ {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT,
366+ XML_L("XML_BLAP_MAX_AMP"),
367+ (long int)
368+ EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_MAXIMUM_AMPLIFICATION_DEFAULT},
369+ {XML_FEATURE_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT,
370+ XML_L("XML_BLAP_ACT_THRES"),
371+ EXPAT_BILLION_LAUGHS_ATTACK_PROTECTION_ACTIVATION_THRESHOLD_DEFAULT},
372+#endif
373+ {XML_FEATURE_END, NULL, 0}};
374
375 return features;
376 }
377
378+#ifdef XML_DTD
379+XML_Bool XMLCALL
380+XML_SetBillionLaughsAttackProtectionMaximumAmplification(
381+ XML_Parser parser, float maximumAmplificationFactor) {
382+ if ((parser == NULL) || (parser->m_parentParser != NULL)
383+ || isnan(maximumAmplificationFactor)
384+ || (maximumAmplificationFactor < 1.0f)) {
385+ return XML_FALSE;
386+ }
387+ parser->m_accounting.maximumAmplificationFactor = maximumAmplificationFactor;
388+ return XML_TRUE;
389+}
390+
391+XML_Bool XMLCALL
392+XML_SetBillionLaughsAttackProtectionActivationThreshold(
393+ XML_Parser parser, unsigned long long activationThresholdBytes) {
394+ if ((parser == NULL) || (parser->m_parentParser != NULL)) {
395+ return XML_FALSE;
396+ }
397+ parser->m_accounting.activationThresholdBytes = activationThresholdBytes;
398+ return XML_TRUE;
399+}
400+#endif /* XML_DTD */
401+
402 /* Initially tag->rawName always points into the parse buffer;
403 for those TAG instances opened while the current parse buffer was
404 processed, and not yet closed, we need to store tag->rawName in a more
405@@ -2441,9 +2557,9 @@ storeRawNames(XML_Parser parser) {
406 static enum XML_Error PTRCALL
407 contentProcessor(XML_Parser parser, const char *start, const char *end,
408 const char **endPtr) {
409- enum XML_Error result
410- = doContent(parser, 0, parser->m_encoding, start, end, endPtr,
411- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
412+ enum XML_Error result = doContent(
413+ parser, 0, parser->m_encoding, start, end, endPtr,
414+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
415 if (result == XML_ERROR_NONE) {
416 if (! storeRawNames(parser))
417 return XML_ERROR_NO_MEMORY;
418@@ -2468,6 +2584,14 @@ externalEntityInitProcessor2(XML_Parser parser, const char *start,
419 int tok = XmlContentTok(parser->m_encoding, start, end, &next);
420 switch (tok) {
421 case XML_TOK_BOM:
422+#ifdef XML_DTD
423+ if (! accountingDiffTolerated(parser, tok, start, next, __LINE__,
424+ XML_ACCOUNT_DIRECT)) {
425+ accountingOnAbort(parser);
426+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
427+ }
428+#endif /* XML_DTD */
429+
430 /* If we are at the end of the buffer, this would cause the next stage,
431 i.e. externalEntityInitProcessor3, to pass control directly to
432 doContent (by detecting XML_TOK_NONE) without processing any xml text
433@@ -2505,6 +2629,10 @@ externalEntityInitProcessor3(XML_Parser parser, const char *start,
434 const char *next = start; /* XmlContentTok doesn't always set the last arg */
435 parser->m_eventPtr = start;
436 tok = XmlContentTok(parser->m_encoding, start, end, &next);
437+ /* Note: These bytes are accounted later in:
438+ - processXmlDecl
439+ - externalEntityContentProcessor
440+ */
441 parser->m_eventEndPtr = next;
442
443 switch (tok) {
444@@ -2546,7 +2674,8 @@ externalEntityContentProcessor(XML_Parser parser, const char *start,
445 const char *end, const char **endPtr) {
446 enum XML_Error result
447 = doContent(parser, 1, parser->m_encoding, start, end, endPtr,
448- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
449+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
450+ XML_ACCOUNT_ENTITY_EXPANSION);
451 if (result == XML_ERROR_NONE) {
452 if (! storeRawNames(parser))
453 return XML_ERROR_NO_MEMORY;
454@@ -2557,7 +2686,7 @@ externalEntityContentProcessor(XML_Parser parser, const char *start,
455 static enum XML_Error
456 doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
457 const char *s, const char *end, const char **nextPtr,
458- XML_Bool haveMore) {
459+ XML_Bool haveMore, enum XML_Account account) {
460 /* save one level of indirection */
461 DTD *const dtd = parser->m_dtd;
462
463@@ -2575,6 +2704,17 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
464 for (;;) {
465 const char *next = s; /* XmlContentTok doesn't always set the last arg */
466 int tok = XmlContentTok(enc, s, end, &next);
467+#ifdef XML_DTD
468+ const char *accountAfter
469+ = ((tok == XML_TOK_TRAILING_RSQB) || (tok == XML_TOK_TRAILING_CR))
470+ ? (haveMore ? s /* i.e. 0 bytes */ : end)
471+ : next;
472+ if (! accountingDiffTolerated(parser, tok, s, accountAfter, __LINE__,
473+ account)) {
474+ accountingOnAbort(parser);
475+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
476+ }
477+#endif
478 *eventEndPP = next;
479 switch (tok) {
480 case XML_TOK_TRAILING_CR:
481@@ -2630,6 +2770,14 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
482 XML_Char ch = (XML_Char)XmlPredefinedEntityName(
483 enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
484 if (ch) {
485+#ifdef XML_DTD
486+ /* NOTE: We are replacing 4-6 characters original input for 1 character
487+ * so there is no amplification and hence recording without
488+ * protection. */
489+ accountingDiffTolerated(parser, tok, (char *)&ch,
490+ ((char *)&ch) + sizeof(XML_Char), __LINE__,
491+ XML_ACCOUNT_ENTITY_EXPANSION);
492+#endif /* XML_DTD */
493 if (parser->m_characterDataHandler)
494 parser->m_characterDataHandler(parser->m_handlerArg, &ch, 1);
495 else if (parser->m_defaultHandler)
496@@ -2748,7 +2896,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
497 }
498 tag->name.str = (XML_Char *)tag->buf;
499 *toPtr = XML_T('\0');
500- result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
501+ result
502+ = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings), account);
503 if (result)
504 return result;
505 if (parser->m_startElementHandler)
506@@ -2772,7 +2921,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
507 if (! name.str)
508 return XML_ERROR_NO_MEMORY;
509 poolFinish(&parser->m_tempPool);
510- result = storeAtts(parser, enc, s, &name, &bindings);
511+ result = storeAtts(parser, enc, s, &name, &bindings,
512+ XML_ACCOUNT_NONE /* token spans whole start tag */);
513 if (result != XML_ERROR_NONE) {
514 freeBindings(parser, bindings);
515 return result;
516@@ -2907,7 +3057,8 @@ doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
517 /* END disabled code */
518 else if (parser->m_defaultHandler)
519 reportDefault(parser, enc, s, next);
520- result = doCdataSection(parser, enc, &next, end, nextPtr, haveMore);
521+ result
522+ = doCdataSection(parser, enc, &next, end, nextPtr, haveMore, account);
523 if (result != XML_ERROR_NONE)
524 return result;
525 else if (! next) {
526@@ -3036,7 +3187,8 @@ freeBindings(XML_Parser parser, BINDING *bindings) {
527 */
528 static enum XML_Error
529 storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
530- TAG_NAME *tagNamePtr, BINDING **bindingsPtr) {
531+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr,
532+ enum XML_Account account) {
533 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
534 ELEMENT_TYPE *elementType;
535 int nDefaultAtts;
536@@ -3146,7 +3298,7 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
537 /* normalize the attribute value */
538 result = storeAttributeValue(
539 parser, enc, isCdata, parser->m_atts[i].valuePtr,
540- parser->m_atts[i].valueEnd, &parser->m_tempPool);
541+ parser->m_atts[i].valueEnd, &parser->m_tempPool, account);
542 if (result)
543 return result;
544 appAtts[attIndex] = poolStart(&parser->m_tempPool);
545@@ -3535,9 +3687,9 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
546 static enum XML_Error PTRCALL
547 cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
548 const char **endPtr) {
549- enum XML_Error result
550- = doCdataSection(parser, parser->m_encoding, &start, end, endPtr,
551- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
552+ enum XML_Error result = doCdataSection(
553+ parser, parser->m_encoding, &start, end, endPtr,
554+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_ACCOUNT_DIRECT);
555 if (result != XML_ERROR_NONE)
556 return result;
557 if (start) {
558@@ -3557,7 +3709,8 @@ cdataSectionProcessor(XML_Parser parser, const char *start, const char *end,
559 */
560 static enum XML_Error
561 doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
562- const char *end, const char **nextPtr, XML_Bool haveMore) {
563+ const char *end, const char **nextPtr, XML_Bool haveMore,
564+ enum XML_Account account) {
565 const char *s = *startPtr;
566 const char **eventPP;
567 const char **eventEndPP;
568@@ -3575,6 +3728,14 @@ doCdataSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
569 for (;;) {
570 const char *next;
571 int tok = XmlCdataSectionTok(enc, s, end, &next);
572+#ifdef XML_DTD
573+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
574+ accountingOnAbort(parser);
575+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
576+ }
577+#else
578+ UNUSED_P(account);
579+#endif
580 *eventEndPP = next;
581 switch (tok) {
582 case XML_TOK_CDATA_SECT_CLOSE:
583@@ -3719,6 +3880,13 @@ doIgnoreSection(XML_Parser parser, const ENCODING *enc, const char **startPtr,
584 *eventPP = s;
585 *startPtr = NULL;
586 tok = XmlIgnoreSectionTok(enc, s, end, &next);
587+# ifdef XML_DTD
588+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
589+ XML_ACCOUNT_DIRECT)) {
590+ accountingOnAbort(parser);
591+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
592+ }
593+# endif
594 *eventEndPP = next;
595 switch (tok) {
596 case XML_TOK_IGNORE_SECT:
597@@ -3803,6 +3971,15 @@ processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *s,
598 const char *versionend;
599 const XML_Char *storedversion = NULL;
600 int standalone = -1;
601+
602+#ifdef XML_DTD
603+ if (! accountingDiffTolerated(parser, XML_TOK_XML_DECL, s, next, __LINE__,
604+ XML_ACCOUNT_DIRECT)) {
605+ accountingOnAbort(parser);
606+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
607+ }
608+#endif
609+
610 if (! (parser->m_ns ? XmlParseXmlDeclNS : XmlParseXmlDecl)(
611 isGeneralTextEntity, parser->m_encoding, s, next, &parser->m_eventPtr,
612 &version, &versionend, &encodingName, &newEncoding, &standalone)) {
613@@ -3952,6 +4129,10 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
614
615 for (;;) {
616 tok = XmlPrologTok(parser->m_encoding, start, end, &next);
617+ /* Note: Except for XML_TOK_BOM below, these bytes are accounted later in:
618+ - storeEntityValue
619+ - processXmlDecl
620+ */
621 parser->m_eventEndPtr = next;
622 if (tok <= 0) {
623 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
624@@ -3970,7 +4151,8 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
625 break;
626 }
627 /* found end of entity value - can store it now */
628- return storeEntityValue(parser, parser->m_encoding, s, end);
629+ return storeEntityValue(parser, parser->m_encoding, s, end,
630+ XML_ACCOUNT_DIRECT);
631 } else if (tok == XML_TOK_XML_DECL) {
632 enum XML_Error result;
633 result = processXmlDecl(parser, 0, start, next);
634@@ -3997,6 +4179,14 @@ entityValueInitProcessor(XML_Parser parser, const char *s, const char *end,
635 */
636 else if (tok == XML_TOK_BOM && next == end
637 && ! parser->m_parsingStatus.finalBuffer) {
638+# ifdef XML_DTD
639+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
640+ XML_ACCOUNT_DIRECT)) {
641+ accountingOnAbort(parser);
642+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
643+ }
644+# endif
645+
646 *nextPtr = next;
647 return XML_ERROR_NONE;
648 }
649@@ -4039,16 +4229,24 @@ externalParEntProcessor(XML_Parser parser, const char *s, const char *end,
650 }
651 /* This would cause the next stage, i.e. doProlog to be passed XML_TOK_BOM.
652 However, when parsing an external subset, doProlog will not accept a BOM
653- as valid, and report a syntax error, so we have to skip the BOM
654+ as valid, and report a syntax error, so we have to skip the BOM, and
655+ account for the BOM bytes.
656 */
657 else if (tok == XML_TOK_BOM) {
658+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
659+ XML_ACCOUNT_DIRECT)) {
660+ accountingOnAbort(parser);
661+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
662+ }
663+
664 s = next;
665 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
666 }
667
668 parser->m_processor = prologProcessor;
669 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
670- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
671+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
672+ XML_ACCOUNT_DIRECT);
673 }
674
675 static enum XML_Error PTRCALL
676@@ -4061,6 +4259,9 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
677
678 for (;;) {
679 tok = XmlPrologTok(enc, start, end, &next);
680+ /* Note: These bytes are accounted later in:
681+ - storeEntityValue
682+ */
683 if (tok <= 0) {
684 if (! parser->m_parsingStatus.finalBuffer && tok != XML_TOK_INVALID) {
685 *nextPtr = s;
686@@ -4078,7 +4279,7 @@ entityValueProcessor(XML_Parser parser, const char *s, const char *end,
687 break;
688 }
689 /* found end of entity value - can store it now */
690- return storeEntityValue(parser, enc, s, end);
691+ return storeEntityValue(parser, enc, s, end, XML_ACCOUNT_DIRECT);
692 }
693 start = next;
694 }
695@@ -4092,13 +4293,14 @@ prologProcessor(XML_Parser parser, const char *s, const char *end,
696 const char *next = s;
697 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
698 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
699- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
700+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
701+ XML_ACCOUNT_DIRECT);
702 }
703
704 static enum XML_Error
705 doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
706 int tok, const char *next, const char **nextPtr, XML_Bool haveMore,
707- XML_Bool allowClosingDoctype) {
708+ XML_Bool allowClosingDoctype, enum XML_Account account) {
709 #ifdef XML_DTD
710 static const XML_Char externalSubsetName[] = {ASCII_HASH, '\0'};
711 #endif /* XML_DTD */
712@@ -4125,6 +4327,10 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
713 static const XML_Char enumValueSep[] = {ASCII_PIPE, '\0'};
714 static const XML_Char enumValueStart[] = {ASCII_LPAREN, '\0'};
715
716+#ifndef XML_DTD
717+ UNUSED_P(account);
718+#endif
719+
720 /* save one level of indirection */
721 DTD *const dtd = parser->m_dtd;
722
723@@ -4189,6 +4395,19 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
724 }
725 }
726 role = XmlTokenRole(&parser->m_prologState, tok, s, next, enc);
727+#ifdef XML_DTD
728+ switch (role) {
729+ case XML_ROLE_INSTANCE_START: // bytes accounted in contentProcessor
730+ case XML_ROLE_XML_DECL: // bytes accounted in processXmlDecl
731+ case XML_ROLE_TEXT_DECL: // bytes accounted in processXmlDecl
732+ break;
733+ default:
734+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__, account)) {
735+ accountingOnAbort(parser);
736+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
737+ }
738+ }
739+#endif
740 switch (role) {
741 case XML_ROLE_XML_DECL: {
742 enum XML_Error result = processXmlDecl(parser, 0, s, next);
743@@ -4464,7 +4683,8 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
744 const XML_Char *attVal;
745 enum XML_Error result = storeAttributeValue(
746 parser, enc, parser->m_declAttributeIsCdata,
747- s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool);
748+ s + enc->minBytesPerChar, next - enc->minBytesPerChar, &dtd->pool,
749+ XML_ACCOUNT_NONE);
750 if (result)
751 return result;
752 attVal = poolStart(&dtd->pool);
753@@ -4497,8 +4717,9 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
754 break;
755 case XML_ROLE_ENTITY_VALUE:
756 if (dtd->keepProcessing) {
757- enum XML_Error result = storeEntityValue(
758- parser, enc, s + enc->minBytesPerChar, next - enc->minBytesPerChar);
759+ enum XML_Error result
760+ = storeEntityValue(parser, enc, s + enc->minBytesPerChar,
761+ next - enc->minBytesPerChar, XML_ACCOUNT_NONE);
762 if (parser->m_declEntity) {
763 parser->m_declEntity->textPtr = poolStart(&dtd->entityValuePool);
764 parser->m_declEntity->textLen
765@@ -4888,12 +5109,15 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
766 if (parser->m_externalEntityRefHandler) {
767 dtd->paramEntityRead = XML_FALSE;
768 entity->open = XML_TRUE;
769+ entityTrackingOnOpen(parser, entity, __LINE__);
770 if (! parser->m_externalEntityRefHandler(
771 parser->m_externalEntityRefHandlerArg, 0, entity->base,
772 entity->systemId, entity->publicId)) {
773+ entityTrackingOnClose(parser, entity, __LINE__);
774 entity->open = XML_FALSE;
775 return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
776 }
777+ entityTrackingOnClose(parser, entity, __LINE__);
778 entity->open = XML_FALSE;
779 handleDefault = XML_FALSE;
780 if (! dtd->paramEntityRead) {
781@@ -5091,6 +5315,13 @@ epilogProcessor(XML_Parser parser, const char *s, const char *end,
782 for (;;) {
783 const char *next = NULL;
784 int tok = XmlPrologTok(parser->m_encoding, s, end, &next);
785+#ifdef XML_DTD
786+ if (! accountingDiffTolerated(parser, tok, s, next, __LINE__,
787+ XML_ACCOUNT_DIRECT)) {
788+ accountingOnAbort(parser);
789+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
790+ }
791+#endif
792 parser->m_eventEndPtr = next;
793 switch (tok) {
794 /* report partial linebreak - it might be the last token */
795@@ -5164,6 +5395,9 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
796 return XML_ERROR_NO_MEMORY;
797 }
798 entity->open = XML_TRUE;
799+#ifdef XML_DTD
800+ entityTrackingOnOpen(parser, entity, __LINE__);
801+#endif
802 entity->processed = 0;
803 openEntity->next = parser->m_openInternalEntities;
804 parser->m_openInternalEntities = openEntity;
805@@ -5182,17 +5416,22 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
806 int tok
807 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
808 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
809- tok, next, &next, XML_FALSE, XML_FALSE);
810+ tok, next, &next, XML_FALSE, XML_FALSE,
811+ XML_ACCOUNT_ENTITY_EXPANSION);
812 } else
813 #endif /* XML_DTD */
814 result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
815- textStart, textEnd, &next, XML_FALSE);
816+ textStart, textEnd, &next, XML_FALSE,
817+ XML_ACCOUNT_ENTITY_EXPANSION);
818
819 if (result == XML_ERROR_NONE) {
820 if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
821 entity->processed = (int)(next - textStart);
822 parser->m_processor = internalEntityProcessor;
823 } else {
824+#ifdef XML_DTD
825+ entityTrackingOnClose(parser, entity, __LINE__);
826+#endif /* XML_DTD */
827 entity->open = XML_FALSE;
828 parser->m_openInternalEntities = openEntity->next;
829 /* put openEntity back in list of free instances */
830@@ -5225,12 +5464,13 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
831 int tok
832 = XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
833 result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
834- tok, next, &next, XML_FALSE, XML_TRUE);
835+ tok, next, &next, XML_FALSE, XML_TRUE,
836+ XML_ACCOUNT_ENTITY_EXPANSION);
837 } else
838 #endif /* XML_DTD */
839 result = doContent(parser, openEntity->startTagLevel,
840 parser->m_internalEncoding, textStart, textEnd, &next,
841- XML_FALSE);
842+ XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
843
844 if (result != XML_ERROR_NONE)
845 return result;
846@@ -5239,6 +5479,9 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
847 entity->processed = (int)(next - (char *)entity->textPtr);
848 return result;
849 } else {
850+#ifdef XML_DTD
851+ entityTrackingOnClose(parser, entity, __LINE__);
852+#endif
853 entity->open = XML_FALSE;
854 parser->m_openInternalEntities = openEntity->next;
855 /* put openEntity back in list of free instances */
856@@ -5252,7 +5495,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
857 parser->m_processor = prologProcessor;
858 tok = XmlPrologTok(parser->m_encoding, s, end, &next);
859 return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
860- (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE);
861+ (XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
862+ XML_ACCOUNT_DIRECT);
863 } else
864 #endif /* XML_DTD */
865 {
866@@ -5260,7 +5504,8 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
867 /* see externalEntityContentProcessor vs contentProcessor */
868 return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
869 s, end, nextPtr,
870- (XML_Bool)! parser->m_parsingStatus.finalBuffer);
871+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
872+ XML_ACCOUNT_DIRECT);
873 }
874 }
875
876@@ -5275,9 +5520,10 @@ errorProcessor(XML_Parser parser, const char *s, const char *end,
877
878 static enum XML_Error
879 storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
880- const char *ptr, const char *end, STRING_POOL *pool) {
881+ const char *ptr, const char *end, STRING_POOL *pool,
882+ enum XML_Account account) {
883 enum XML_Error result
884- = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
885+ = appendAttributeValue(parser, enc, isCdata, ptr, end, pool, account);
886 if (result)
887 return result;
888 if (! isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
889@@ -5289,11 +5535,22 @@ storeAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
890
891 static enum XML_Error
892 appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
893- const char *ptr, const char *end, STRING_POOL *pool) {
894+ const char *ptr, const char *end, STRING_POOL *pool,
895+ enum XML_Account account) {
896 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
897+#ifndef XML_DTD
898+ UNUSED_P(account);
899+#endif
900+
901 for (;;) {
902 const char *next;
903 int tok = XmlAttributeValueTok(enc, ptr, end, &next);
904+#ifdef XML_DTD
905+ if (! accountingDiffTolerated(parser, tok, ptr, next, __LINE__, account)) {
906+ accountingOnAbort(parser);
907+ return XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
908+ }
909+#endif
910 switch (tok) {
911 case XML_TOK_NONE:
912 return XML_ERROR_NONE;
913@@ -5353,6 +5610,14 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
914 XML_Char ch = (XML_Char)XmlPredefinedEntityName(
915 enc, ptr + enc->minBytesPerChar, next - enc->minBytesPerChar);
916 if (ch) {
917+#ifdef XML_DTD
918+ /* NOTE: We are replacing 4-6 characters original input for 1 character
919+ * so there is no amplification and hence recording without
920+ * protection. */
921+ accountingDiffTolerated(parser, tok, (char *)&ch,
922+ ((char *)&ch) + sizeof(XML_Char), __LINE__,
923+ XML_ACCOUNT_ENTITY_EXPANSION);
924+#endif /* XML_DTD */
925 if (! poolAppendChar(pool, ch))
926 return XML_ERROR_NO_MEMORY;
927 break;
928@@ -5430,9 +5695,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
929 enum XML_Error result;
930 const XML_Char *textEnd = entity->textPtr + entity->textLen;
931 entity->open = XML_TRUE;
932+#ifdef XML_DTD
933+ entityTrackingOnOpen(parser, entity, __LINE__);
934+#endif
935 result = appendAttributeValue(parser, parser->m_internalEncoding,
936- isCdata, (char *)entity->textPtr,
937- (char *)textEnd, pool);
938+ isCdata, (const char *)entity->textPtr,
939+ (const char *)textEnd, pool,
940+ XML_ACCOUNT_ENTITY_EXPANSION);
941+#ifdef XML_DTD
942+ entityTrackingOnClose(parser, entity, __LINE__);
943+#endif
944 entity->open = XML_FALSE;
945 if (result)
946 return result;
947@@ -5462,13 +5734,16 @@ appendAttributeValue(XML_Parser parser, const ENCODING *enc, XML_Bool isCdata,
948
949 static enum XML_Error
950 storeEntityValue(XML_Parser parser, const ENCODING *enc,
951- const char *entityTextPtr, const char *entityTextEnd) {
952+ const char *entityTextPtr, const char *entityTextEnd,
953+ enum XML_Account account) {
954 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
955 STRING_POOL *pool = &(dtd->entityValuePool);
956 enum XML_Error result = XML_ERROR_NONE;
957 #ifdef XML_DTD
958 int oldInEntityValue = parser->m_prologState.inEntityValue;
959 parser->m_prologState.inEntityValue = 1;
960+#else
961+ UNUSED_P(account);
962 #endif /* XML_DTD */
963 /* never return Null for the value argument in EntityDeclHandler,
964 since this would indicate an external entity; therefore we
965@@ -5481,6 +5756,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
966 for (;;) {
967 const char *next;
968 int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
969+
970+#ifdef XML_DTD
971+ if (! accountingDiffTolerated(parser, tok, entityTextPtr, next, __LINE__,
972+ account)) {
973+ accountingOnAbort(parser);
974+ result = XML_ERROR_AMPLIFICATION_LIMIT_BREACH;
975+ goto endEntityValue;
976+ }
977+#endif
978+
979 switch (tok) {
980 case XML_TOK_PARAM_ENTITY_REF:
981 #ifdef XML_DTD
982@@ -5516,13 +5801,16 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
983 if (parser->m_externalEntityRefHandler) {
984 dtd->paramEntityRead = XML_FALSE;
985 entity->open = XML_TRUE;
986+ entityTrackingOnOpen(parser, entity, __LINE__);
987 if (! parser->m_externalEntityRefHandler(
988 parser->m_externalEntityRefHandlerArg, 0, entity->base,
989 entity->systemId, entity->publicId)) {
990+ entityTrackingOnClose(parser, entity, __LINE__);
991 entity->open = XML_FALSE;
992 result = XML_ERROR_EXTERNAL_ENTITY_HANDLING;
993 goto endEntityValue;
994 }
995+ entityTrackingOnClose(parser, entity, __LINE__);
996 entity->open = XML_FALSE;
997 if (! dtd->paramEntityRead)
998 dtd->keepProcessing = dtd->standalone;
999@@ -5530,9 +5818,12 @@ storeEntityValue(XML_Parser parser, const ENCODING *enc,
1000 dtd->keepProcessing = dtd->standalone;
1001 } else {
1002 entity->open = XML_TRUE;
1003+ entityTrackingOnOpen(parser, entity, __LINE__);
1004 result = storeEntityValue(
1005- parser, parser->m_internalEncoding, (char *)entity->textPtr,
1006- (char *)(entity->textPtr + entity->textLen));
1007+ parser, parser->m_internalEncoding, (const char *)entity->textPtr,
1008+ (const char *)(entity->textPtr + entity->textLen),
1009+ XML_ACCOUNT_ENTITY_EXPANSION);
1010+ entityTrackingOnClose(parser, entity, __LINE__);
1011 entity->open = XML_FALSE;
1012 if (result)
1013 goto endEntityValue;
1014@@ -6893,3 +7184,741 @@ copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
1015 memcpy(result, s, charsRequired * sizeof(XML_Char));
1016 return result;
1017 }
1018+
1019+#ifdef XML_DTD
1020+
1021+static float
1022+accountingGetCurrentAmplification(XML_Parser rootParser) {
1023+ const XmlBigCount countBytesOutput
1024+ = rootParser->m_accounting.countBytesDirect
1025+ + rootParser->m_accounting.countBytesIndirect;
1026+ const float amplificationFactor
1027+ = rootParser->m_accounting.countBytesDirect
1028+ ? (countBytesOutput
1029+ / (float)(rootParser->m_accounting.countBytesDirect))
1030+ : 1.0f;
1031+ assert(! rootParser->m_parentParser);
1032+ return amplificationFactor;
1033+}
1034+
1035+static void
1036+accountingReportStats(XML_Parser originParser, const char *epilog) {
1037+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
1038+ assert(! rootParser->m_parentParser);
1039+
1040+ if (rootParser->m_accounting.debugLevel < 1) {
1041+ return;
1042+ }
1043+
1044+ const float amplificationFactor
1045+ = accountingGetCurrentAmplification(rootParser);
1046+ fprintf(stderr,
1047+ "expat: Accounting(%p): Direct " EXPAT_FMT_ULL(
1048+ "10") ", indirect " EXPAT_FMT_ULL("10") ", amplification %8.2f%s",
1049+ (void *)rootParser, rootParser->m_accounting.countBytesDirect,
1050+ rootParser->m_accounting.countBytesIndirect,
1051+ (double)amplificationFactor, epilog);
1052+}
1053+
1054+static void
1055+accountingOnAbort(XML_Parser originParser) {
1056+ accountingReportStats(originParser, " ABORTING\n");
1057+}
1058+
1059+static void
1060+accountingReportDiff(XML_Parser rootParser,
1061+ unsigned int levelsAwayFromRootParser, const char *before,
1062+ const char *after, ptrdiff_t bytesMore, int source_line,
1063+ enum XML_Account account) {
1064+ assert(! rootParser->m_parentParser);
1065+
1066+ fprintf(stderr,
1067+ " (+" EXPAT_FMT_PTRDIFF_T("6") " bytes %s|%d, xmlparse.c:%d) %*s\"",
1068+ bytesMore, (account == XML_ACCOUNT_DIRECT) ? "DIR" : "EXP",
1069+ levelsAwayFromRootParser, source_line, 10, "");
1070+
1071+ const char ellipis[] = "[..]";
1072+ const size_t ellipsisLength = sizeof(ellipis) /* because compile-time */ - 1;
1073+ const unsigned int contextLength = 10;
1074+
1075+ /* Note: Performance is of no concern here */
1076+ const char *walker = before;
1077+ if ((rootParser->m_accounting.debugLevel >= 3)
1078+ || (after - before)
1079+ <= (ptrdiff_t)(contextLength + ellipsisLength + contextLength)) {
1080+ for (; walker < after; walker++) {
1081+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
1082+ }
1083+ } else {
1084+ for (; walker < before + contextLength; walker++) {
1085+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
1086+ }
1087+ fprintf(stderr, ellipis);
1088+ walker = after - contextLength;
1089+ for (; walker < after; walker++) {
1090+ fprintf(stderr, "%s", unsignedCharToPrintable(walker[0]));
1091+ }
1092+ }
1093+ fprintf(stderr, "\"\n");
1094+}
1095+
1096+static XML_Bool
1097+accountingDiffTolerated(XML_Parser originParser, int tok, const char *before,
1098+ const char *after, int source_line,
1099+ enum XML_Account account) {
1100+ /* Note: We need to check the token type *first* to be sure that
1101+ * we can even access variable <after>, safely.
1102+ * E.g. for XML_TOK_NONE <after> may hold an invalid pointer. */
1103+ switch (tok) {
1104+ case XML_TOK_INVALID:
1105+ case XML_TOK_PARTIAL:
1106+ case XML_TOK_PARTIAL_CHAR:
1107+ case XML_TOK_NONE:
1108+ return XML_TRUE;
1109+ }
1110+
1111+ if (account == XML_ACCOUNT_NONE)
1112+ return XML_TRUE; /* because these bytes have been accounted for, already */
1113+
1114+ unsigned int levelsAwayFromRootParser;
1115+ const XML_Parser rootParser
1116+ = getRootParserOf(originParser, &levelsAwayFromRootParser);
1117+ assert(! rootParser->m_parentParser);
1118+
1119+ const int isDirect
1120+ = (account == XML_ACCOUNT_DIRECT) && (originParser == rootParser);
1121+ const ptrdiff_t bytesMore = after - before;
1122+
1123+ XmlBigCount *const additionTarget
1124+ = isDirect ? &rootParser->m_accounting.countBytesDirect
1125+ : &rootParser->m_accounting.countBytesIndirect;
1126+
1127+ /* Detect and avoid integer overflow */
1128+ if (*additionTarget > (XmlBigCount)(-1) - (XmlBigCount)bytesMore)
1129+ return XML_FALSE;
1130+ *additionTarget += bytesMore;
1131+
1132+ const XmlBigCount countBytesOutput
1133+ = rootParser->m_accounting.countBytesDirect
1134+ + rootParser->m_accounting.countBytesIndirect;
1135+ const float amplificationFactor
1136+ = accountingGetCurrentAmplification(rootParser);
1137+ const XML_Bool tolerated
1138+ = (countBytesOutput < rootParser->m_accounting.activationThresholdBytes)
1139+ || (amplificationFactor
1140+ <= rootParser->m_accounting.maximumAmplificationFactor);
1141+
1142+ if (rootParser->m_accounting.debugLevel >= 2) {
1143+ accountingReportStats(rootParser, "");
1144+ accountingReportDiff(rootParser, levelsAwayFromRootParser, before, after,
1145+ bytesMore, source_line, account);
1146+ }
1147+
1148+ return tolerated;
1149+}
1150+
1151+static void
1152+entityTrackingReportStats(XML_Parser rootParser, ENTITY *entity,
1153+ const char *action, int sourceLine) {
1154+ assert(! rootParser->m_parentParser);
1155+ if (rootParser->m_entity_stats.debugLevel < 1)
1156+ return;
1157+
1158+# if defined(XML_UNICODE)
1159+ const char *const entityName = "[..]";
1160+# else
1161+ const char *const entityName = entity->name;
1162+# endif
1163+
1164+ fprintf(
1165+ stderr,
1166+ "expat: Entities(%p): Count %9d, depth %2d/%2d %*s%s%s; %s length %d (xmlparse.c:%d)\n",
1167+ (void *)rootParser, rootParser->m_entity_stats.countEverOpened,
1168+ rootParser->m_entity_stats.currentDepth,
1169+ rootParser->m_entity_stats.maximumDepthSeen,
1170+ (rootParser->m_entity_stats.currentDepth - 1) * 2, "",
1171+ entity->is_param ? "%" : "&", entityName, action, entity->textLen,
1172+ sourceLine);
1173+}
1174+
1175+static void
1176+entityTrackingOnOpen(XML_Parser originParser, ENTITY *entity, int sourceLine) {
1177+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
1178+ assert(! rootParser->m_parentParser);
1179+
1180+ rootParser->m_entity_stats.countEverOpened++;
1181+ rootParser->m_entity_stats.currentDepth++;
1182+ if (rootParser->m_entity_stats.currentDepth
1183+ > rootParser->m_entity_stats.maximumDepthSeen) {
1184+ rootParser->m_entity_stats.maximumDepthSeen++;
1185+ }
1186+
1187+ entityTrackingReportStats(rootParser, entity, "OPEN ", sourceLine);
1188+}
1189+
1190+static void
1191+entityTrackingOnClose(XML_Parser originParser, ENTITY *entity, int sourceLine) {
1192+ const XML_Parser rootParser = getRootParserOf(originParser, NULL);
1193+ assert(! rootParser->m_parentParser);
1194+
1195+ entityTrackingReportStats(rootParser, entity, "CLOSE", sourceLine);
1196+ rootParser->m_entity_stats.currentDepth--;
1197+}
1198+
1199+static XML_Parser
1200+getRootParserOf(XML_Parser parser, unsigned int *outLevelDiff) {
1201+ XML_Parser rootParser = parser;
1202+ unsigned int stepsTakenUpwards = 0;
1203+ while (rootParser->m_parentParser) {
1204+ rootParser = rootParser->m_parentParser;
1205+ stepsTakenUpwards++;
1206+ }
1207+ assert(! rootParser->m_parentParser);
1208+ if (outLevelDiff != NULL) {
1209+ *outLevelDiff = stepsTakenUpwards;
1210+ }
1211+ return rootParser;
1212+}
1213+
1214+static const char *
1215+unsignedCharToPrintable(unsigned char c) {
1216+ switch (c) {
1217+ case 0:
1218+ return "\\0";
1219+ case 1:
1220+ return "\\x1";
1221+ case 2:
1222+ return "\\x2";
1223+ case 3:
1224+ return "\\x3";
1225+ case 4:
1226+ return "\\x4";
1227+ case 5:
1228+ return "\\x5";
1229+ case 6:
1230+ return "\\x6";
1231+ case 7:
1232+ return "\\x7";
1233+ case 8:
1234+ return "\\x8";
1235+ case 9:
1236+ return "\\t";
1237+ case 10:
1238+ return "\\n";
1239+ case 11:
1240+ return "\\xB";
1241+ case 12:
1242+ return "\\xC";
1243+ case 13:
1244+ return "\\r";
1245+ case 14:
1246+ return "\\xE";
1247+ case 15:
1248+ return "\\xF";
1249+ case 16:
1250+ return "\\x10";
1251+ case 17:
1252+ return "\\x11";
1253+ case 18:
1254+ return "\\x12";
1255+ case 19:
1256+ return "\\x13";
1257+ case 20:
1258+ return "\\x14";
1259+ case 21:
1260+ return "\\x15";
1261+ case 22:
1262+ return "\\x16";
1263+ case 23:
1264+ return "\\x17";
1265+ case 24:
1266+ return "\\x18";
1267+ case 25:
1268+ return "\\x19";
1269+ case 26:
1270+ return "\\x1A";
1271+ case 27:
1272+ return "\\x1B";
1273+ case 28:
1274+ return "\\x1C";
1275+ case 29:
1276+ return "\\x1D";
1277+ case 30:
1278+ return "\\x1E";
1279+ case 31:
1280+ return "\\x1F";
1281+ case 32:
1282+ return " ";
1283+ case 33:
1284+ return "!";
1285+ case 34:
1286+ return "\\\"";
1287+ case 35:
1288+ return "#";
1289+ case 36:
1290+ return "$";
1291+ case 37:
1292+ return "%";
1293+ case 38:
1294+ return "&";
1295+ case 39:
1296+ return "'";
1297+ case 40:
1298+ return "(";
1299+ case 41:
1300+ return ")";
1301+ case 42:
1302+ return "*";
1303+ case 43:
1304+ return "+";
1305+ case 44:
1306+ return ",";
1307+ case 45:
1308+ return "-";
1309+ case 46:
1310+ return ".";
1311+ case 47:
1312+ return "/";
1313+ case 48:
1314+ return "0";
1315+ case 49:
1316+ return "1";
1317+ case 50:
1318+ return "2";
1319+ case 51:
1320+ return "3";
1321+ case 52:
1322+ return "4";
1323+ case 53:
1324+ return "5";
1325+ case 54:
1326+ return "6";
1327+ case 55:
1328+ return "7";
1329+ case 56:
1330+ return "8";
1331+ case 57:
1332+ return "9";
1333+ case 58:
1334+ return ":";
1335+ case 59:
1336+ return ";";
1337+ case 60:
1338+ return "<";
1339+ case 61:
1340+ return "=";
1341+ case 62:
1342+ return ">";
1343+ case 63:
1344+ return "?";
1345+ case 64:
1346+ return "@";
1347+ case 65:
1348+ return "A";
1349+ case 66:
1350+ return "B";
1351+ case 67:
1352+ return "C";
1353+ case 68:
1354+ return "D";
1355+ case 69:
1356+ return "E";
1357+ case 70:
1358+ return "F";
1359+ case 71:
1360+ return "G";
1361+ case 72:
1362+ return "H";
1363+ case 73:
1364+ return "I";
1365+ case 74:
1366+ return "J";
1367+ case 75:
1368+ return "K";
1369+ case 76:
1370+ return "L";
1371+ case 77:
1372+ return "M";
1373+ case 78:
1374+ return "N";
1375+ case 79:
1376+ return "O";
1377+ case 80:
1378+ return "P";
1379+ case 81:
1380+ return "Q";
1381+ case 82:
1382+ return "R";
1383+ case 83:
1384+ return "S";
1385+ case 84:
1386+ return "T";
1387+ case 85:
1388+ return "U";
1389+ case 86:
1390+ return "V";
1391+ case 87:
1392+ return "W";
1393+ case 88:
1394+ return "X";
1395+ case 89:
1396+ return "Y";
1397+ case 90:
1398+ return "Z";
1399+ case 91:
1400+ return "[";
1401+ case 92:
1402+ return "\\\\";
1403+ case 93:
1404+ return "]";
1405+ case 94:
1406+ return "^";
1407+ case 95:
1408+ return "_";
1409+ case 96:
1410+ return "`";
1411+ case 97:
1412+ return "a";
1413+ case 98:
1414+ return "b";
1415+ case 99:
1416+ return "c";
1417+ case 100:
1418+ return "d";
1419+ case 101:
1420+ return "e";
1421+ case 102:
1422+ return "f";
1423+ case 103:
1424+ return "g";
1425+ case 104:
1426+ return "h";
1427+ case 105:
1428+ return "i";
1429+ case 106:
1430+ return "j";
1431+ case 107:
1432+ return "k";
1433+ case 108:
1434+ return "l";
1435+ case 109:
1436+ return "m";
1437+ case 110:
1438+ return "n";
1439+ case 111:
1440+ return "o";
1441+ case 112:
1442+ return "p";
1443+ case 113:
1444+ return "q";
1445+ case 114:
1446+ return "r";
1447+ case 115:
1448+ return "s";
1449+ case 116:
1450+ return "t";
1451+ case 117:
1452+ return "u";
1453+ case 118:
1454+ return "v";
1455+ case 119:
1456+ return "w";
1457+ case 120:
1458+ return "x";
1459+ case 121:
1460+ return "y";
1461+ case 122:
1462+ return "z";
1463+ case 123:
1464+ return "{";
1465+ case 124:
1466+ return "|";
1467+ case 125:
1468+ return "}";
1469+ case 126:
1470+ return "~";
1471+ case 127:
1472+ return "\\x7F";
1473+ case 128:
1474+ return "\\x80";
1475+ case 129:
1476+ return "\\x81";
1477+ case 130:
1478+ return "\\x82";
1479+ case 131:
1480+ return "\\x83";
1481+ case 132:
1482+ return "\\x84";
1483+ case 133:
1484+ return "\\x85";
1485+ case 134:
1486+ return "\\x86";
1487+ case 135:
1488+ return "\\x87";
1489+ case 136:
1490+ return "\\x88";
1491+ case 137:
1492+ return "\\x89";
1493+ case 138:
1494+ return "\\x8A";
1495+ case 139:
1496+ return "\\x8B";
1497+ case 140:
1498+ return "\\x8C";
1499+ case 141:
1500+ return "\\x8D";
1501+ case 142:
1502+ return "\\x8E";
1503+ case 143:
1504+ return "\\x8F";
1505+ case 144:
1506+ return "\\x90";
1507+ case 145:
1508+ return "\\x91";
1509+ case 146:
1510+ return "\\x92";
1511+ case 147:
1512+ return "\\x93";
1513+ case 148:
1514+ return "\\x94";
1515+ case 149:
1516+ return "\\x95";
1517+ case 150:
1518+ return "\\x96";
1519+ case 151:
1520+ return "\\x97";
1521+ case 152:
1522+ return "\\x98";
1523+ case 153:
1524+ return "\\x99";
1525+ case 154:
1526+ return "\\x9A";
1527+ case 155:
1528+ return "\\x9B";
1529+ case 156:
1530+ return "\\x9C";
1531+ case 157:
1532+ return "\\x9D";
1533+ case 158:
1534+ return "\\x9E";
1535+ case 159:
1536+ return "\\x9F";
1537+ case 160:
1538+ return "\\xA0";
1539+ case 161:
1540+ return "\\xA1";
1541+ case 162:
1542+ return "\\xA2";
1543+ case 163:
1544+ return "\\xA3";
1545+ case 164:
1546+ return "\\xA4";
1547+ case 165:
1548+ return "\\xA5";
1549+ case 166:
1550+ return "\\xA6";
1551+ case 167:
1552+ return "\\xA7";
1553+ case 168:
1554+ return "\\xA8";
1555+ case 169:
1556+ return "\\xA9";
1557+ case 170:
1558+ return "\\xAA";
1559+ case 171:
1560+ return "\\xAB";
1561+ case 172:
1562+ return "\\xAC";
1563+ case 173:
1564+ return "\\xAD";
1565+ case 174:
1566+ return "\\xAE";
1567+ case 175:
1568+ return "\\xAF";
1569+ case 176:
1570+ return "\\xB0";
1571+ case 177:
1572+ return "\\xB1";
1573+ case 178:
1574+ return "\\xB2";
1575+ case 179:
1576+ return "\\xB3";
1577+ case 180:
1578+ return "\\xB4";
1579+ case 181:
1580+ return "\\xB5";
1581+ case 182:
1582+ return "\\xB6";
1583+ case 183:
1584+ return "\\xB7";
1585+ case 184:
1586+ return "\\xB8";
1587+ case 185:
1588+ return "\\xB9";
1589+ case 186:
1590+ return "\\xBA";
1591+ case 187:
1592+ return "\\xBB";
1593+ case 188:
1594+ return "\\xBC";
1595+ case 189:
1596+ return "\\xBD";
1597+ case 190:
1598+ return "\\xBE";
1599+ case 191:
1600+ return "\\xBF";
1601+ case 192:
1602+ return "\\xC0";
1603+ case 193:
1604+ return "\\xC1";
1605+ case 194:
1606+ return "\\xC2";
1607+ case 195:
1608+ return "\\xC3";
1609+ case 196:
1610+ return "\\xC4";
1611+ case 197:
1612+ return "\\xC5";
1613+ case 198:
1614+ return "\\xC6";
1615+ case 199:
1616+ return "\\xC7";
1617+ case 200:
1618+ return "\\xC8";
1619+ case 201:
1620+ return "\\xC9";
1621+ case 202:
1622+ return "\\xCA";
1623+ case 203:
1624+ return "\\xCB";
1625+ case 204:
1626+ return "\\xCC";
1627+ case 205:
1628+ return "\\xCD";
1629+ case 206:
1630+ return "\\xCE";
1631+ case 207:
1632+ return "\\xCF";
1633+ case 208:
1634+ return "\\xD0";
1635+ case 209:
1636+ return "\\xD1";
1637+ case 210:
1638+ return "\\xD2";
1639+ case 211:
1640+ return "\\xD3";
1641+ case 212:
1642+ return "\\xD4";
1643+ case 213:
1644+ return "\\xD5";
1645+ case 214:
1646+ return "\\xD6";
1647+ case 215:
1648+ return "\\xD7";
1649+ case 216:
1650+ return "\\xD8";
1651+ case 217:
1652+ return "\\xD9";
1653+ case 218:
1654+ return "\\xDA";
1655+ case 219:
1656+ return "\\xDB";
1657+ case 220:
1658+ return "\\xDC";
1659+ case 221:
1660+ return "\\xDD";
1661+ case 222:
1662+ return "\\xDE";
1663+ case 223:
1664+ return "\\xDF";
1665+ case 224:
1666+ return "\\xE0";
1667+ case 225:
1668+ return "\\xE1";
1669+ case 226:
1670+ return "\\xE2";
1671+ case 227:
1672+ return "\\xE3";
1673+ case 228:
1674+ return "\\xE4";
1675+ case 229:
1676+ return "\\xE5";
1677+ case 230:
1678+ return "\\xE6";
1679+ case 231:
1680+ return "\\xE7";
1681+ case 232:
1682+ return "\\xE8";
1683+ case 233:
1684+ return "\\xE9";
1685+ case 234:
1686+ return "\\xEA";
1687+ case 235:
1688+ return "\\xEB";
1689+ case 236:
1690+ return "\\xEC";
1691+ case 237:
1692+ return "\\xED";
1693+ case 238:
1694+ return "\\xEE";
1695+ case 239:
1696+ return "\\xEF";
1697+ case 240:
1698+ return "\\xF0";
1699+ case 241:
1700+ return "\\xF1";
1701+ case 242:
1702+ return "\\xF2";
1703+ case 243:
1704+ return "\\xF3";
1705+ case 244:
1706+ return "\\xF4";
1707+ case 245:
1708+ return "\\xF5";
1709+ case 246:
1710+ return "\\xF6";
1711+ case 247:
1712+ return "\\xF7";
1713+ case 248:
1714+ return "\\xF8";
1715+ case 249:
1716+ return "\\xF9";
1717+ case 250:
1718+ return "\\xFA";
1719+ case 251:
1720+ return "\\xFB";
1721+ case 252:
1722+ return "\\xFC";
1723+ case 253:
1724+ return "\\xFD";
1725+ case 254:
1726+ return "\\xFE";
1727+ case 255:
1728+ return "\\xFF";
1729+ default:
1730+ assert(0); /* never gets here */
1731+ return "dead code";
1732+ }
1733+ assert(0); /* never gets here */
1734+}
1735+
1736+#endif /* XML_DTD */
1737+
1738+static unsigned long
1739+getDebugLevel(const char *variableName, unsigned long defaultDebugLevel) {
1740+ const char *const valueOrNull = getenv(variableName);
1741+ if (valueOrNull == NULL) {
1742+ return defaultDebugLevel;
1743+ }
1744+ const char *const value = valueOrNull;
1745+
1746+ errno = 0;
1747+ char *afterValue = (char *)value;
1748+ unsigned long debugLevel = strtoul(value, &afterValue, 10);
1749+ if ((errno != 0) || (afterValue[0] != '\0')) {
1750+ errno = 0;
1751+ return defaultDebugLevel;
1752+ }
1753+
1754+ return debugLevel;
1755+}
1756--
17572.32.0
1758
diff --git a/meta/recipes-core/expat/expat/CVE-2021-45960.patch b/meta/recipes-core/expat/expat/CVE-2021-45960.patch
new file mode 100644
index 0000000000..523449e22c
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2021-45960.patch
@@ -0,0 +1,65 @@
1From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Mon, 27 Dec 2021 20:15:02 +0100
4Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function
5 storeAtts (CVE-2021-45960)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/pull/534/commits/0adcb34c49bee5b19bd29b16a578c510c23597ea
9
10CVE: CVE-2021-45960
11Signed-off-by: Steve Sakoman <steve@sakoman.com>
12
13---
14 expat/lib/xmlparse.c | 31 +++++++++++++++++++++++++++++--
15 1 file changed, 29 insertions(+), 2 deletions(-)
16
17diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
18index d730f41c3..b47c31b05 100644
19--- a/lib/xmlparse.c
20+++ b/lib/xmlparse.c
21@@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
22 if (nPrefixes) {
23 int j; /* hash table index */
24 unsigned long version = parser->m_nsAttsVersion;
25- int nsAttsSize = (int)1 << parser->m_nsAttsPower;
26+
27+ /* Detect and prevent invalid shift */
28+ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
29+ return XML_ERROR_NO_MEMORY;
30+ }
31+
32+ unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
33 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
34 /* size of hash table must be at least 2 * (# of prefixed attributes) */
35 if ((nPrefixes << 1)
36@@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
37 ;
38 if (parser->m_nsAttsPower < 3)
39 parser->m_nsAttsPower = 3;
40- nsAttsSize = (int)1 << parser->m_nsAttsPower;
41+
42+ /* Detect and prevent invalid shift */
43+ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
44+ /* Restore actual size of memory in m_nsAtts */
45+ parser->m_nsAttsPower = oldNsAttsPower;
46+ return XML_ERROR_NO_MEMORY;
47+ }
48+
49+ nsAttsSize = 1u << parser->m_nsAttsPower;
50+
51+ /* Detect and prevent integer overflow.
52+ * The preprocessor guard addresses the "always false" warning
53+ * from -Wtype-limits on platforms where
54+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
55+#if UINT_MAX >= SIZE_MAX
56+ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
57+ /* Restore actual size of memory in m_nsAtts */
58+ parser->m_nsAttsPower = oldNsAttsPower;
59+ return XML_ERROR_NO_MEMORY;
60+ }
61+#endif
62+
63 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
64 nsAttsSize * sizeof(NS_ATT));
65 if (! temp) {
diff --git a/meta/recipes-core/expat/expat/CVE-2021-46143.patch b/meta/recipes-core/expat/expat/CVE-2021-46143.patch
new file mode 100644
index 0000000000..b1a726d9a8
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2021-46143.patch
@@ -0,0 +1,49 @@
1From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Sat, 25 Dec 2021 20:52:08 +0100
4Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function
5 doProlog (CVE-2021-46143)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/pull/538/commits/85ae9a2d7d0e9358f356b33977b842df8ebaec2b
9
10CVE: CVE-2021-46143
11
12Signed-off-by: Steve Sakoman <steve@sakoman.com>
13---
14 expat/lib/xmlparse.c | 15 +++++++++++++++
15 1 file changed, 15 insertions(+)
16
17diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
18index b47c31b0..8f243126 100644
19--- a/lib/xmlparse.c
20+++ b/lib/xmlparse.c
21@@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
22 if (parser->m_prologState.level >= parser->m_groupSize) {
23 if (parser->m_groupSize) {
24 {
25+ /* Detect and prevent integer overflow */
26+ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
27+ return XML_ERROR_NO_MEMORY;
28+ }
29+
30 char *const new_connector = (char *)REALLOC(
31 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
32 if (new_connector == NULL) {
33@@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
34 }
35
36 if (dtd->scaffIndex) {
37+ /* Detect and prevent integer overflow.
38+ * The preprocessor guard addresses the "always false" warning
39+ * from -Wtype-limits on platforms where
40+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
41+#if UINT_MAX >= SIZE_MAX
42+ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
43+ return XML_ERROR_NO_MEMORY;
44+ }
45+#endif
46+
47 int *const new_scaff_index = (int *)REALLOC(
48 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
49 if (new_scaff_index == NULL)
diff --git a/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch
new file mode 100644
index 0000000000..e569fbc7ab
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch
@@ -0,0 +1,257 @@
1From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Thu, 30 Dec 2021 22:46:03 +0100
4Subject: [PATCH] lib: Prevent integer overflow at multiple places
5 (CVE-2022-22822 to CVE-2022-22827)
6
7The involved functions are:
8- addBinding (CVE-2022-22822)
9- build_model (CVE-2022-22823)
10- defineAttribute (CVE-2022-22824)
11- lookup (CVE-2022-22825)
12- nextScaffoldPart (CVE-2022-22826)
13- storeAtts (CVE-2022-22827)
14
15Upstream-Status: Backport:
16https://github.com/libexpat/libexpat/pull/539/commits/9f93e8036e842329863bf20395b8fb8f73834d9e
17
18CVE: CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827
19Signed-off-by: Steve Sakoman <steve@sakoman.com>
20
21---
22 expat/lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++-
23 1 file changed, 151 insertions(+), 2 deletions(-)
24
25diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
26index 8f243126..575e73ee 100644
27--- a/lib/xmlparse.c
28+++ b/lib/xmlparse.c
29@@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
30
31 /* get the attributes from the tokenizer */
32 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
33+
34+ /* Detect and prevent integer overflow */
35+ if (n > INT_MAX - nDefaultAtts) {
36+ return XML_ERROR_NO_MEMORY;
37+ }
38+
39 if (n + nDefaultAtts > parser->m_attsSize) {
40 int oldAttsSize = parser->m_attsSize;
41 ATTRIBUTE *temp;
42 #ifdef XML_ATTR_INFO
43 XML_AttrInfo *temp2;
44 #endif
45+
46+ /* Detect and prevent integer overflow */
47+ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
48+ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
49+ return XML_ERROR_NO_MEMORY;
50+ }
51+
52 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
53+
54+ /* Detect and prevent integer overflow.
55+ * The preprocessor guard addresses the "always false" warning
56+ * from -Wtype-limits on platforms where
57+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
58+#if UINT_MAX >= SIZE_MAX
59+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
60+ parser->m_attsSize = oldAttsSize;
61+ return XML_ERROR_NO_MEMORY;
62+ }
63+#endif
64+
65 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
66 parser->m_attsSize * sizeof(ATTRIBUTE));
67 if (temp == NULL) {
68@@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
69 }
70 parser->m_atts = temp;
71 #ifdef XML_ATTR_INFO
72+ /* Detect and prevent integer overflow.
73+ * The preprocessor guard addresses the "always false" warning
74+ * from -Wtype-limits on platforms where
75+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
76+# if UINT_MAX >= SIZE_MAX
77+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
78+ parser->m_attsSize = oldAttsSize;
79+ return XML_ERROR_NO_MEMORY;
80+ }
81+# endif
82+
83 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
84 parser->m_attsSize * sizeof(XML_AttrInfo));
85 if (temp2 == NULL) {
86@@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
87 tagNamePtr->prefixLen = prefixLen;
88 for (i = 0; localPart[i++];)
89 ; /* i includes null terminator */
90+
91+ /* Detect and prevent integer overflow */
92+ if (binding->uriLen > INT_MAX - prefixLen
93+ || i > INT_MAX - (binding->uriLen + prefixLen)) {
94+ return XML_ERROR_NO_MEMORY;
95+ }
96+
97 n = i + binding->uriLen + prefixLen;
98 if (n > binding->uriAlloc) {
99 TAG *p;
100+
101+ /* Detect and prevent integer overflow */
102+ if (n > INT_MAX - EXPAND_SPARE) {
103+ return XML_ERROR_NO_MEMORY;
104+ }
105+ /* Detect and prevent integer overflow.
106+ * The preprocessor guard addresses the "always false" warning
107+ * from -Wtype-limits on platforms where
108+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
109+#if UINT_MAX >= SIZE_MAX
110+ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
111+ return XML_ERROR_NO_MEMORY;
112+ }
113+#endif
114+
115 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
116 if (! uri)
117 return XML_ERROR_NO_MEMORY;
118@@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
119 if (parser->m_freeBindingList) {
120 b = parser->m_freeBindingList;
121 if (len > b->uriAlloc) {
122+ /* Detect and prevent integer overflow */
123+ if (len > INT_MAX - EXPAND_SPARE) {
124+ return XML_ERROR_NO_MEMORY;
125+ }
126+
127+ /* Detect and prevent integer overflow.
128+ * The preprocessor guard addresses the "always false" warning
129+ * from -Wtype-limits on platforms where
130+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
131+#if UINT_MAX >= SIZE_MAX
132+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
133+ return XML_ERROR_NO_MEMORY;
134+ }
135+#endif
136+
137 XML_Char *temp = (XML_Char *)REALLOC(
138 parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
139 if (temp == NULL)
140@@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
141 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
142 if (! b)
143 return XML_ERROR_NO_MEMORY;
144+
145+ /* Detect and prevent integer overflow */
146+ if (len > INT_MAX - EXPAND_SPARE) {
147+ return XML_ERROR_NO_MEMORY;
148+ }
149+ /* Detect and prevent integer overflow.
150+ * The preprocessor guard addresses the "always false" warning
151+ * from -Wtype-limits on platforms where
152+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
153+#if UINT_MAX >= SIZE_MAX
154+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
155+ return XML_ERROR_NO_MEMORY;
156+ }
157+#endif
158+
159 b->uri
160 = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
161 if (! b->uri) {
162@@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
163 }
164 } else {
165 DEFAULT_ATTRIBUTE *temp;
166+
167+ /* Detect and prevent integer overflow */
168+ if (type->allocDefaultAtts > INT_MAX / 2) {
169+ return 0;
170+ }
171+
172 int count = type->allocDefaultAtts * 2;
173+
174+ /* Detect and prevent integer overflow.
175+ * The preprocessor guard addresses the "always false" warning
176+ * from -Wtype-limits on platforms where
177+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
178+#if UINT_MAX >= SIZE_MAX
179+ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
180+ return 0;
181+ }
182+#endif
183+
184 temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
185 (count * sizeof(DEFAULT_ATTRIBUTE)));
186 if (temp == NULL)
187@@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
188 /* check for overflow (table is half full) */
189 if (table->used >> (table->power - 1)) {
190 unsigned char newPower = table->power + 1;
191+
192+ /* Detect and prevent invalid shift */
193+ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
194+ return NULL;
195+ }
196+
197 size_t newSize = (size_t)1 << newPower;
198 unsigned long newMask = (unsigned long)newSize - 1;
199+
200+ /* Detect and prevent integer overflow */
201+ if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
202+ return NULL;
203+ }
204+
205 size_t tsize = newSize * sizeof(NAMED *);
206 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
207 if (! newV)
208@@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) {
209 if (dtd->scaffCount >= dtd->scaffSize) {
210 CONTENT_SCAFFOLD *temp;
211 if (dtd->scaffold) {
212+ /* Detect and prevent integer overflow */
213+ if (dtd->scaffSize > UINT_MAX / 2u) {
214+ return -1;
215+ }
216+ /* Detect and prevent integer overflow.
217+ * The preprocessor guard addresses the "always false" warning
218+ * from -Wtype-limits on platforms where
219+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
220+#if UINT_MAX >= SIZE_MAX
221+ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
222+ return -1;
223+ }
224+#endif
225+
226 temp = (CONTENT_SCAFFOLD *)REALLOC(
227 parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
228 if (temp == NULL)
229@@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) {
230 XML_Content *ret;
231 XML_Content *cpos;
232 XML_Char *str;
233- int allocsize = (dtd->scaffCount * sizeof(XML_Content)
234- + (dtd->contentStringLen * sizeof(XML_Char)));
235+
236+ /* Detect and prevent integer overflow.
237+ * The preprocessor guard addresses the "always false" warning
238+ * from -Wtype-limits on platforms where
239+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
240+#if UINT_MAX >= SIZE_MAX
241+ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
242+ return NULL;
243+ }
244+ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
245+ return NULL;
246+ }
247+#endif
248+ if (dtd->scaffCount * sizeof(XML_Content)
249+ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
250+ return NULL;
251+ }
252+
253+ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
254+ + (dtd->contentStringLen * sizeof(XML_Char)));
255
256 ret = (XML_Content *)MALLOC(parser, allocsize);
257 if (! ret)
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23852.patch b/meta/recipes-core/expat/expat/CVE-2022-23852.patch
new file mode 100644
index 0000000000..41425c108b
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-23852.patch
@@ -0,0 +1,33 @@
1From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Sat, 22 Jan 2022 17:48:00 +0100
4Subject: [PATCH] lib: Detect and prevent integer overflow in XML_GetBuffer
5 (CVE-2022-23852)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/commit/847a645152f5ebc10ac63b74b604d0c1a79fae40
9
10CVE: CVE-2022-23852
11
12Signed-off-by: Steve Sakoman <steve@sakoman.com>
13
14---
15 expat/lib/xmlparse.c | 5 +++++
16 1 file changed, 5 insertions(+)
17
18diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
19index d54af683..5ce31402 100644
20--- a/lib/xmlparse.c
21+++ b/lib/xmlparse.c
22@@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
23 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
24 if (keep > XML_CONTEXT_BYTES)
25 keep = XML_CONTEXT_BYTES;
26+ /* Detect and prevent integer overflow */
27+ if (keep > INT_MAX - neededSize) {
28+ parser->m_errorCode = XML_ERROR_NO_MEMORY;
29+ return NULL;
30+ }
31 neededSize += keep;
32 #endif /* defined XML_CONTEXT_BYTES */
33 if (neededSize
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23990.patch b/meta/recipes-core/expat/expat/CVE-2022-23990.patch
new file mode 100644
index 0000000000..c599517b3e
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-23990.patch
@@ -0,0 +1,49 @@
1From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Wed, 26 Jan 2022 02:36:43 +0100
4Subject: [PATCH] lib: Prevent integer overflow in doProlog (CVE-2022-23990)
5
6The change from "int nameLen" to "size_t nameLen"
7addresses the overflow on "nameLen++" in code
8"for (; name[nameLen++];)" right above the second
9change in the patch.
10
11Upstream-Status: Backport:
12https://github.com/libexpat/libexpat/pull/551/commits/ede41d1e186ed2aba88a06e84cac839b770af3a1
13
14CVE: CVE-2022-23990
15
16Signed-off-by: Steve Sakoman <steve@sakoman.com>
17
18---
19 lib/xmlparse.c | 10 ++++++++--
20 1 file changed, 8 insertions(+), 2 deletions(-)
21
22diff --git a/lib/xmlparse.c b/expat/lib/xmlparse.c
23index 5ce31402..d1d17005 100644
24--- a/lib/xmlparse.c
25+++ b/lib/xmlparse.c
26@@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
27 if (dtd->in_eldecl) {
28 ELEMENT_TYPE *el;
29 const XML_Char *name;
30- int nameLen;
31+ size_t nameLen;
32 const char *nxt
33 = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
34 int myindex = nextScaffoldPart(parser);
35@@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
36 nameLen = 0;
37 for (; name[nameLen++];)
38 ;
39- dtd->contentStringLen += nameLen;
40+
41+ /* Detect and prevent integer overflow */
42+ if (nameLen > UINT_MAX - dtd->contentStringLen) {
43+ return XML_ERROR_NO_MEMORY;
44+ }
45+
46+ dtd->contentStringLen += (unsigned)nameLen;
47 if (parser->m_elementDeclHandler)
48 handleDefault = XML_FALSE;
49 }
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25235.patch b/meta/recipes-core/expat/expat/CVE-2022-25235.patch
new file mode 100644
index 0000000000..be9182a5c1
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25235.patch
@@ -0,0 +1,283 @@
1From ee2a5b50e7d1940ba8745715b62ceb9efd3a96da Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Tue, 8 Feb 2022 17:37:14 +0100
4Subject: [PATCH] lib: Drop unused macro UTF8_GET_NAMING
5
6Upstream-Status: Backport
7https://github.com/libexpat/libexpat/pull/562/commits
8
9CVE: CVE-2022-25235
10
11Signed-off-by: Steve Sakoman <steve@sakoman.com>
12
13---
14 expat/lib/xmltok.c | 5 -----
15 1 file changed, 5 deletions(-)
16
17diff --git a/lib/xmltok.c b/lib/xmltok.c
18index a72200e8..3bddf125 100644
19--- a/lib/xmltok.c
20+++ b/lib/xmltok.c
21@@ -95,11 +95,6 @@
22 + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
23 & (1u << (((byte)[2]) & 0x1F)))
24
25-#define UTF8_GET_NAMING(pages, p, n) \
26- ((n) == 2 \
27- ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
28- : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0))
29-
30 /* Detection of invalid UTF-8 sequences is based on Table 3.1B
31 of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
32 with the additional restriction of not allowing the Unicode
33From 3f0a0cb644438d4d8e3294cd0b1245d0edb0c6c6 Mon Sep 17 00:00:00 2001
34From: Sebastian Pipping <sebastian@pipping.org>
35Date: Tue, 8 Feb 2022 04:32:20 +0100
36Subject: [PATCH] lib: Add missing validation of encoding (CVE-2022-25235)
37
38---
39 expat/lib/xmltok_impl.c | 8 ++++++--
40 1 file changed, 6 insertions(+), 2 deletions(-)
41
42diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
43index 0430591b4..64a3b2c15 100644
44--- a/lib/xmltok_impl.c
45+++ b/lib/xmltok_impl.c
46@@ -61,7 +61,7 @@
47 case BT_LEAD##n: \
48 if (end - ptr < n) \
49 return XML_TOK_PARTIAL_CHAR; \
50- if (! IS_NAME_CHAR(enc, ptr, n)) { \
51+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \
52 *nextTokPtr = ptr; \
53 return XML_TOK_INVALID; \
54 } \
55@@ -90,7 +90,7 @@
56 case BT_LEAD##n: \
57 if (end - ptr < n) \
58 return XML_TOK_PARTIAL_CHAR; \
59- if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \
60+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \
61 *nextTokPtr = ptr; \
62 return XML_TOK_INVALID; \
63 } \
64@@ -1134,6 +1134,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
65 case BT_LEAD##n: \
66 if (end - ptr < n) \
67 return XML_TOK_PARTIAL_CHAR; \
68+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
69+ *nextTokPtr = ptr; \
70+ return XML_TOK_INVALID; \
71+ } \
72 if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
73 ptr += n; \
74 tok = XML_TOK_NAME; \
75From c85a3025e7a1be086dc34e7559fbc543914d047f Mon Sep 17 00:00:00 2001
76From: Sebastian Pipping <sebastian@pipping.org>
77Date: Wed, 9 Feb 2022 01:00:38 +0100
78Subject: [PATCH] lib: Add comments to BT_LEAD* cases where encoding has
79 already been validated
80
81---
82 expat/lib/xmltok_impl.c | 10 +++++-----
83 1 file changed, 5 insertions(+), 5 deletions(-)
84
85diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
86index 64a3b2c1..84ff35f9 100644
87--- a/lib/xmltok_impl.c
88+++ b/lib/xmltok_impl.c
89@@ -1266,7 +1266,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
90 switch (BYTE_TYPE(enc, ptr)) {
91 # define LEAD_CASE(n) \
92 case BT_LEAD##n: \
93- ptr += n; \
94+ ptr += n; /* NOTE: The encoding has already been validated. */ \
95 break;
96 LEAD_CASE(2)
97 LEAD_CASE(3)
98@@ -1335,7 +1335,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
99 switch (BYTE_TYPE(enc, ptr)) {
100 # define LEAD_CASE(n) \
101 case BT_LEAD##n: \
102- ptr += n; \
103+ ptr += n; /* NOTE: The encoding has already been validated. */ \
104 break;
105 LEAD_CASE(2)
106 LEAD_CASE(3)
107@@ -1514,7 +1514,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
108 state = inName; \
109 }
110 # define LEAD_CASE(n) \
111- case BT_LEAD##n: \
112+ case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \
113 START_NAME ptr += (n - MINBPC(enc)); \
114 break;
115 LEAD_CASE(2)
116@@ -1726,7 +1726,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
117 switch (BYTE_TYPE(enc, ptr)) {
118 # define LEAD_CASE(n) \
119 case BT_LEAD##n: \
120- ptr += n; \
121+ ptr += n; /* NOTE: The encoding has already been validated. */ \
122 break;
123 LEAD_CASE(2)
124 LEAD_CASE(3)
125@@ -1771,7 +1771,7 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
126 switch (BYTE_TYPE(enc, ptr)) {
127 # define LEAD_CASE(n) \
128 case BT_LEAD##n: \
129- ptr += n; \
130+ ptr += n; /* NOTE: The encoding has already been validated. */ \
131 break;
132 LEAD_CASE(2)
133 LEAD_CASE(3)
134From 6a5510bc6b7efe743356296724e0b38300f05379 Mon Sep 17 00:00:00 2001
135From: Sebastian Pipping <sebastian@pipping.org>
136Date: Tue, 8 Feb 2022 04:06:21 +0100
137Subject: [PATCH] tests: Cover missing validation of encoding (CVE-2022-25235)
138
139---
140 expat/tests/runtests.c | 109 +++++++++++++++++++++++++++++++++++++++++
141 1 file changed, 109 insertions(+)
142
143diff --git a/tests/runtests.c b/tests/runtests.c
144index bc5344b1..9b155b82 100644
145--- a/tests/runtests.c
146+++ b/tests/runtests.c
147@@ -5998,6 +5998,105 @@ START_TEST(test_utf8_in_cdata_section_2) {
148 }
149 END_TEST
150
151+START_TEST(test_utf8_in_start_tags) {
152+ struct test_case {
153+ bool goodName;
154+ bool goodNameStart;
155+ const char *tagName;
156+ };
157+
158+ // The idea with the tests below is this:
159+ // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
160+ // go to isNever and are hence not a concern.
161+ //
162+ // We start with a character that is a valid name character
163+ // (or even name-start character, see XML 1.0r4 spec) and then we flip
164+ // single bits at places where (1) the result leaves the UTF-8 encoding space
165+ // and (2) we stay in the same n-byte sequence family.
166+ //
167+ // The flipped bits are highlighted in angle brackets in comments,
168+ // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
169+ // the most significant bit to 1 to leave UTF-8 encoding space.
170+ struct test_case cases[] = {
171+ // 1-byte UTF-8: [0xxx xxxx]
172+ {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':'
173+ {false, false, "\xBA"}, // [<1>011 1010]
174+ {true, false, "\x39"}, // [0011 1001] = ASCII nine '9'
175+ {false, false, "\xB9"}, // [<1>011 1001]
176+
177+ // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
178+ {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] =
179+ // Arabic small waw U+06E5
180+ {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
181+ {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
182+ {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
183+ {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] =
184+ // combining char U+0301
185+ {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
186+ {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
187+ {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
188+
189+ // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
190+ {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] =
191+ // Devanagari Letter A U+0905
192+ {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
193+ {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
194+ {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
195+ {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
196+ {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
197+ {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] =
198+ // combining char U+0901
199+ {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
200+ {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
201+ {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
202+ {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
203+ {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
204+ };
205+ const bool atNameStart[] = {true, false};
206+
207+ size_t i = 0;
208+ char doc[1024];
209+ size_t failCount = 0;
210+
211+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
212+ size_t j = 0;
213+ for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
214+ const bool expectedSuccess
215+ = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
216+ sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
217+ XML_Parser parser = XML_ParserCreate(NULL);
218+
219+ const enum XML_Status status
220+ = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
221+
222+ bool success = true;
223+ if ((status == XML_STATUS_OK) != expectedSuccess) {
224+ success = false;
225+ }
226+ if ((status == XML_STATUS_ERROR)
227+ && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
228+ success = false;
229+ }
230+
231+ if (! success) {
232+ fprintf(
233+ stderr,
234+ "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
235+ (unsigned)i + 1u, atNameStart[j] ? " " : "not ",
236+ (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
237+ failCount++;
238+ }
239+
240+ XML_ParserFree(parser);
241+ }
242+ }
243+
244+ if (failCount > 0) {
245+ fail("UTF-8 regression detected");
246+ }
247+}
248+END_TEST
249+
250 /* Test trailing spaces in elements are accepted */
251 static void XMLCALL
252 record_element_end_handler(void *userData, const XML_Char *name) {
253@@ -6175,6 +6274,14 @@ START_TEST(test_bad_doctype) {
254 }
255 END_TEST
256
257+START_TEST(test_bad_doctype_utf8) {
258+ const char *text = "<!DOCTYPE \xDB\x25"
259+ "doc><doc/>"; // [1101 1011] [<0>010 0101]
260+ expect_failure(text, XML_ERROR_INVALID_TOKEN,
261+ "Invalid UTF-8 in DOCTYPE not faulted");
262+}
263+END_TEST
264+
265 START_TEST(test_bad_doctype_utf16) {
266 const char text[] =
267 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
268@@ -11870,6 +11977,7 @@ make_suite(void) {
269 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
270 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
271 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
272+ tcase_add_test(tc_basic, test_utf8_in_start_tags);
273 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
274 tcase_add_test(tc_basic, test_utf16_attribute);
275 tcase_add_test(tc_basic, test_utf16_second_attr);
276@@ -11878,6 +11986,7 @@ make_suite(void) {
277 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
278 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
279 tcase_add_test(tc_basic, test_bad_doctype);
280+ tcase_add_test(tc_basic, test_bad_doctype_utf8);
281 tcase_add_test(tc_basic, test_bad_doctype_utf16);
282 tcase_add_test(tc_basic, test_bad_doctype_plus);
283 tcase_add_test(tc_basic, test_bad_doctype_star);
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236.patch b/meta/recipes-core/expat/expat/CVE-2022-25236.patch
new file mode 100644
index 0000000000..ba6443fc6a
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25236.patch
@@ -0,0 +1,129 @@
1From 6881a4fc8596307ab9ff2e85e605afa2e413ab71 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Sat, 12 Feb 2022 00:19:13 +0100
4Subject: [PATCH] lib: Fix (harmless) use of uninitialized memory
5
6Upstream-Status: Backport
7https://github.com/libexpat/libexpat/pull/561/commits
8
9CVE: CVE-2022-25236
10
11Signed-off-by: Steve Sakoman <steve@sakoman.com>
12
13---
14 expat/lib/xmlparse.c | 6 ++----
15 1 file changed, 2 insertions(+), 4 deletions(-)
16
17diff --git a/lib/xmlparse.c b/lib/xmlparse.c
18index 902895d5..c768f856 100644
19--- a/lib/xmlparse.c
20+++ b/lib/xmlparse.c
21@@ -718,8 +718,7 @@ XML_ParserCreate(const XML_Char *encodingName) {
22
23 XML_Parser XMLCALL
24 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
25- XML_Char tmp[2];
26- *tmp = nsSep;
27+ XML_Char tmp[2] = {nsSep, 0};
28 return XML_ParserCreate_MM(encodingName, NULL, tmp);
29 }
30
31@@ -1344,8 +1343,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
32 would be otherwise.
33 */
34 if (parser->m_ns) {
35- XML_Char tmp[2];
36- *tmp = parser->m_namespaceSeparator;
37+ XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
38 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
39 } else {
40 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
41From a2fe525e660badd64b6c557c2b1ec26ddc07f6e4 Mon Sep 17 00:00:00 2001
42From: Sebastian Pipping <sebastian@pipping.org>
43Date: Sat, 12 Feb 2022 01:09:29 +0100
44Subject: [PATCH] lib: Protect against malicious namespace declarations
45 (CVE-2022-25236)
46
47---
48 expat/lib/xmlparse.c | 11 +++++++++++
49 1 file changed, 11 insertions(+)
50
51diff --git a/lib/xmlparse.c b/lib/xmlparse.c
52index c768f856..a3aef88c 100644
53--- a/lib/xmlparse.c
54+++ b/lib/xmlparse.c
55@@ -3754,6 +3754,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
56 if (! mustBeXML && isXMLNS
57 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
58 isXMLNS = XML_FALSE;
59+
60+ // NOTE: While Expat does not validate namespace URIs against RFC 3986,
61+ // we have to at least make sure that the XML processor on top of
62+ // Expat (that is splitting tag names by namespace separator into
63+ // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
64+ // by an attacker putting additional namespace separator characters
65+ // into namespace declarations. That would be ambiguous and not to
66+ // be expected.
67+ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
68+ return XML_ERROR_SYNTAX;
69+ }
70 }
71 isXML = isXML && len == xmlLen;
72 isXMLNS = isXMLNS && len == xmlnsLen;
73From 2de077423fb22750ebea599677d523b53cb93b1d Mon Sep 17 00:00:00 2001
74From: Sebastian Pipping <sebastian@pipping.org>
75Date: Sat, 12 Feb 2022 00:51:43 +0100
76Subject: [PATCH] tests: Cover CVE-2022-25236
77
78---
79 expat/tests/runtests.c | 30 ++++++++++++++++++++++++++++++
80 1 file changed, 30 insertions(+)
81
82diff --git a/tests/runtests.c b/tests/runtests.c
83index d07203f2..bc5344b1 100644
84--- a/tests/runtests.c
85+++ b/tests/runtests.c
86@@ -7220,6 +7220,35 @@ START_TEST(test_ns_double_colon_doctype) {
87 }
88 END_TEST
89
90+START_TEST(test_ns_separator_in_uri) {
91+ struct test_case {
92+ enum XML_Status expectedStatus;
93+ const char *doc;
94+ };
95+ struct test_case cases[] = {
96+ {XML_STATUS_OK, "<doc xmlns='one_two' />"},
97+ {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
98+ };
99+
100+ size_t i = 0;
101+ size_t failCount = 0;
102+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
103+ XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
104+ XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
105+ if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
106+ /*isFinal*/ XML_TRUE)
107+ != cases[i].expectedStatus) {
108+ failCount++;
109+ }
110+ XML_ParserFree(parser);
111+ }
112+
113+ if (failCount) {
114+ fail("Namespace separator handling is broken");
115+ }
116+}
117+END_TEST
118+
119 /* Control variable; the number of times duff_allocator() will successfully
120 * allocate */
121 #define ALLOC_ALWAYS_SUCCEED (-1)
122@@ -11905,6 +11934,7 @@ make_suite(void) {
123 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
124 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
125 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
126+ tcase_add_test(tc_namespace, test_ns_separator_in_uri);
127
128 suite_add_tcase(s, tc_misc);
129 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch b/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch
new file mode 100644
index 0000000000..af255e8cb5
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25313-regression.patch
@@ -0,0 +1,131 @@
1From b12f34fe32821a69dc12ff9a021daca0856de238 Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Sat, 19 Feb 2022 23:59:25 +0000
4Subject: [PATCH] Fix build_model regression.
5
6The iterative approach in build_model failed to fill children arrays
7correctly. A preorder traversal is not required and turned out to be the
8culprit. Use an easier algorithm:
9
10Add nodes from scaffold tree starting at index 0 (root) to the target
11array whenever children are encountered. This ensures that children
12are adjacent to each other. This complies with the recursive version.
13
14Store only the scaffold index in numchildren field to prevent a direct
15processing of these children, which would require a recursive solution.
16This allows the algorithm to iterate through the target array from start
17to end without jumping back and forth, converting on the fly.
18
19Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
20---
21 lib/xmlparse.c | 79 ++++++++++++++++++++++++++------------------
22 1 file changed, 47 insertions(+), 32 deletions(-)
23
24diff --git a/lib/xmlparse.c b/lib/xmlparse.c
25index c479a258..84885b5a 100644
26--- a/lib/xmlparse.c
27+++ b/lib/xmlparse.c
28@@ -7373,39 +7373,58 @@ build_model(XML_Parser parser) {
29 *
30 * The iterative approach works as follows:
31 *
32- * - We use space in the target array for building a temporary stack structure
33- * while that space is still unused.
34- * The stack grows from the array's end downwards and the "actual data"
35- * grows from the start upwards, sequentially.
36- * (Because stack grows downwards, pushing onto the stack is a decrement
37- * while popping off the stack is an increment.)
38+ * - We have two writing pointers, both walking up the result array; one does
39+ * the work, the other creates "jobs" for its colleague to do, and leads
40+ * the way:
41 *
42- * - A stack element appears as a regular XML_Content node on the outside,
43- * but only uses a single field -- numchildren -- to store the source
44- * tree node array index. These are the breadcrumbs leading the way back
45- * during pre-order (node first) depth-first traversal.
46+ * - The faster one, pointer jobDest, always leads and writes "what job
47+ * to do" by the other, once they reach that place in the
48+ * array: leader "jobDest" stores the source node array index (relative
49+ * to array dtd->scaffold) in field "numchildren".
50 *
51- * - The reason we know the stack will never grow into (or overlap with)
52- * the area with data of value at the start of the array is because
53- * the overall number of elements to process matches the size of the array,
54- * and the sum of fully processed nodes and yet-to-be processed nodes
55- * on the stack, cannot be more than the total number of nodes.
56- * It is possible for the top of the stack and the about-to-write node
57- * to meet, but that is safe because we get the source index out
58- * before doing any writes on that node.
59+ * - The slower one, pointer dest, looks at the value stored in the
60+ * "numchildren" field (which actually holds a source node array index
61+ * at that time) and puts the real data from dtd->scaffold in.
62+ *
63+ * - Before the loop starts, jobDest writes source array index 0
64+ * (where the root node is located) so that dest will have something to do
65+ * when it starts operation.
66+ *
67+ * - Whenever nodes with children are encountered, jobDest appends
68+ * them as new jobs, in order. As a result, tree node siblings are
69+ * adjacent in the resulting array, for example:
70+ *
71+ * [0] root, has two children
72+ * [1] first child of 0, has three children
73+ * [3] first child of 1, does not have children
74+ * [4] second child of 1, does not have children
75+ * [5] third child of 1, does not have children
76+ * [2] second child of 0, does not have children
77+ *
78+ * Or (the same data) presented in flat array view:
79+ *
80+ * [0] root, has two children
81+ *
82+ * [1] first child of 0, has three children
83+ * [2] second child of 0, does not have children
84+ *
85+ * [3] first child of 1, does not have children
86+ * [4] second child of 1, does not have children
87+ * [5] third child of 1, does not have children
88+ *
89+ * - The algorithm repeats until all target array indices have been processed.
90 */
91 XML_Content *dest = ret; /* tree node writing location, moves upwards */
92 XML_Content *const destLimit = &ret[dtd->scaffCount];
93- XML_Content *const stackBottom = &ret[dtd->scaffCount];
94- XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
95+ XML_Content *jobDest = ret; /* next free writing location in target array */
96 str = (XML_Char *)&ret[dtd->scaffCount];
97
98- /* Push source tree root node index onto the stack */
99- (--stackTop)->numchildren = 0;
100+ /* Add the starting job, the root node (index 0) of the source tree */
101+ (jobDest++)->numchildren = 0;
102
103 for (; dest < destLimit; dest++) {
104- /* Pop source tree node index off the stack */
105- const int src_node = (int)(stackTop++)->numchildren;
106+ /* Retrieve source tree array index from job storage */
107+ const int src_node = (int)dest->numchildren;
108
109 /* Convert item */
110 dest->type = dtd->scaffold[src_node].type;
111@@ -7427,16 +7446,12 @@ build_model(XML_Parser parser) {
112 int cn;
113 dest->name = NULL;
114 dest->numchildren = dtd->scaffold[src_node].childcnt;
115- dest->children = &dest[1];
116+ dest->children = jobDest;
117
118- /* Push children to the stack
119- * in a way where the first child ends up at the top of the
120- * (downwards growing) stack, in order to be processed first. */
121- stackTop -= dest->numchildren;
122+ /* Append scaffold indices of children to array */
123 for (i = 0, cn = dtd->scaffold[src_node].firstchild;
124- i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
125- (stackTop + i)->numchildren = (unsigned int)cn;
126- }
127+ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib)
128+ (jobDest++)->numchildren = (unsigned int)cn;
129 }
130 }
131
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25313.patch b/meta/recipes-core/expat/expat/CVE-2022-25313.patch
new file mode 100644
index 0000000000..470d66e9dd
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25313.patch
@@ -0,0 +1,230 @@
1From 9b4ce651b26557f16103c3a366c91934ecd439ab Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Tue, 15 Feb 2022 11:54:29 +0000
4Subject: [PATCH] Prevent stack exhaustion in build_model
5
6It is possible to trigger stack exhaustion in build_model function if
7depth of nested children in DTD element is large enough. This happens
8because build_node is a recursively called function within build_model.
9
10The code has been adjusted to run iteratively. It uses the already
11allocated heap space as temporary stack (growing from top to bottom).
12
13Output is identical to recursive version. No new fields in data
14structures were added, i.e. it keeps full API and ABI compatibility.
15Instead the numchildren variable is used to temporarily keep the
16index of items (uint vs int).
17
18Documentation and readability improvements kindly added by Sebastian.
19
20Proof of Concept:
21
221. Compile poc binary which parses XML file line by line
23
24```
25cat > poc.c << EOF
26 #include <err.h>
27 #include <expat.h>
28 #include <stdio.h>
29
30 XML_Parser parser;
31
32 static void XMLCALL
33 dummy_element_decl_handler(void *userData, const XML_Char *name,
34 XML_Content *model) {
35 XML_FreeContentModel(parser, model);
36 }
37
38 int main(int argc, char *argv[]) {
39 FILE *fp;
40 char *p = NULL;
41 size_t s = 0;
42 ssize_t l;
43 if (argc != 2)
44 errx(1, "usage: poc poc.xml");
45 if ((parser = XML_ParserCreate(NULL)) == NULL)
46 errx(1, "XML_ParserCreate");
47 XML_SetElementDeclHandler(parser, dummy_element_decl_handler);
48 if ((fp = fopen(argv[1], "r")) == NULL)
49 err(1, "fopen");
50 while ((l = getline(&p, &s, fp)) > 0)
51 if (XML_Parse(parser, p, (int)l, XML_FALSE) != XML_STATUS_OK)
52 errx(1, "XML_Parse");
53 XML_ParserFree(parser);
54 free(p);
55 fclose(fp);
56 return 0;
57 }
58EOF
59cc -std=c11 -D_POSIX_C_SOURCE=200809L -lexpat -o poc poc.c
60```
61
622. Create XML file with a lot of nested groups in DTD element
63
64```
65cat > poc.xml.zst.b64 << EOF
66KLUv/aQkACAAPAEA+DwhRE9DVFlQRSB1d3UgWwo8IUVMRU1FTlQgdXd1CigBAHv/58AJAgAQKAIA
67ECgCABAoAgAQKAIAECgCABAoAgAQKHwAAChvd28KKQIA2/8gV24XBAIAECkCABApAgAQKQIAECkC
68ABApAgAQKQIAEClVAAAgPl0+CgEA4A4I2VwwnQ==
69EOF
70base64 -d poc.xml.zst.b64 | zstd -d > poc.xml
71```
72
733. Run Proof of Concept
74
75```
76./poc poc.xml
77```
78
79Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
80
81Upstream-Status: Backport
82https://github.com/libexpat/libexpat/pull/558/commits/9b4ce651b26557f16103c3a366c91934ecd439ab
83
84CVE: CVE-2022-25313
85
86Signed-off-by: Steve Sakoman <steve@sakoman.com>
87
88---
89 expat/lib/xmlparse.c | 116 +++++++++++++++++++++++++++++--------------
90 1 file changed, 79 insertions(+), 37 deletions(-)
91
92diff --git a/lib/xmlparse.c b/lib/xmlparse.c
93index 4b43e613..594cf12c 100644
94--- a/lib/xmlparse.c
95+++ b/lib/xmlparse.c
96@@ -7317,44 +7317,15 @@ nextScaffoldPart(XML_Parser parser) {
97 return next;
98 }
99
100-static void
101-build_node(XML_Parser parser, int src_node, XML_Content *dest,
102- XML_Content **contpos, XML_Char **strpos) {
103- DTD *const dtd = parser->m_dtd; /* save one level of indirection */
104- dest->type = dtd->scaffold[src_node].type;
105- dest->quant = dtd->scaffold[src_node].quant;
106- if (dest->type == XML_CTYPE_NAME) {
107- const XML_Char *src;
108- dest->name = *strpos;
109- src = dtd->scaffold[src_node].name;
110- for (;;) {
111- *(*strpos)++ = *src;
112- if (! *src)
113- break;
114- src++;
115- }
116- dest->numchildren = 0;
117- dest->children = NULL;
118- } else {
119- unsigned int i;
120- int cn;
121- dest->numchildren = dtd->scaffold[src_node].childcnt;
122- dest->children = *contpos;
123- *contpos += dest->numchildren;
124- for (i = 0, cn = dtd->scaffold[src_node].firstchild; i < dest->numchildren;
125- i++, cn = dtd->scaffold[cn].nextsib) {
126- build_node(parser, cn, &(dest->children[i]), contpos, strpos);
127- }
128- dest->name = NULL;
129- }
130-}
131-
132 static XML_Content *
133 build_model(XML_Parser parser) {
134+ /* Function build_model transforms the existing parser->m_dtd->scaffold
135+ * array of CONTENT_SCAFFOLD tree nodes into a new array of
136+ * XML_Content tree nodes followed by a gapless list of zero-terminated
137+ * strings. */
138 DTD *const dtd = parser->m_dtd; /* save one level of indirection */
139 XML_Content *ret;
140- XML_Content *cpos;
141- XML_Char *str;
142+ XML_Char *str; /* the current string writing location */
143
144 /* Detect and prevent integer overflow.
145 * The preprocessor guard addresses the "always false" warning
146@@ -7380,10 +7351,81 @@ build_model(XML_Parser parser) {
147 if (! ret)
148 return NULL;
149
150- str = (XML_Char *)(&ret[dtd->scaffCount]);
151- cpos = &ret[1];
152+ /* What follows is an iterative implementation (of what was previously done
153+ * recursively in a dedicated function called "build_node". The old recursive
154+ * build_node could be forced into stack exhaustion from input as small as a
155+ * few megabyte, and so that was a security issue. Hence, a function call
156+ * stack is avoided now by resolving recursion.)
157+ *
158+ * The iterative approach works as follows:
159+ *
160+ * - We use space in the target array for building a temporary stack structure
161+ * while that space is still unused.
162+ * The stack grows from the array's end downwards and the "actual data"
163+ * grows from the start upwards, sequentially.
164+ * (Because stack grows downwards, pushing onto the stack is a decrement
165+ * while popping off the stack is an increment.)
166+ *
167+ * - A stack element appears as a regular XML_Content node on the outside,
168+ * but only uses a single field -- numchildren -- to store the source
169+ * tree node array index. These are the breadcrumbs leading the way back
170+ * during pre-order (node first) depth-first traversal.
171+ *
172+ * - The reason we know the stack will never grow into (or overlap with)
173+ * the area with data of value at the start of the array is because
174+ * the overall number of elements to process matches the size of the array,
175+ * and the sum of fully processed nodes and yet-to-be processed nodes
176+ * on the stack, cannot be more than the total number of nodes.
177+ * It is possible for the top of the stack and the about-to-write node
178+ * to meet, but that is safe because we get the source index out
179+ * before doing any writes on that node.
180+ */
181+ XML_Content *dest = ret; /* tree node writing location, moves upwards */
182+ XML_Content *const destLimit = &ret[dtd->scaffCount];
183+ XML_Content *const stackBottom = &ret[dtd->scaffCount];
184+ XML_Content *stackTop = stackBottom; /* i.e. stack is initially empty */
185+ str = (XML_Char *)&ret[dtd->scaffCount];
186+
187+ /* Push source tree root node index onto the stack */
188+ (--stackTop)->numchildren = 0;
189+
190+ for (; dest < destLimit; dest++) {
191+ /* Pop source tree node index off the stack */
192+ const int src_node = (int)(stackTop++)->numchildren;
193+
194+ /* Convert item */
195+ dest->type = dtd->scaffold[src_node].type;
196+ dest->quant = dtd->scaffold[src_node].quant;
197+ if (dest->type == XML_CTYPE_NAME) {
198+ const XML_Char *src;
199+ dest->name = str;
200+ src = dtd->scaffold[src_node].name;
201+ for (;;) {
202+ *str++ = *src;
203+ if (! *src)
204+ break;
205+ src++;
206+ }
207+ dest->numchildren = 0;
208+ dest->children = NULL;
209+ } else {
210+ unsigned int i;
211+ int cn;
212+ dest->name = NULL;
213+ dest->numchildren = dtd->scaffold[src_node].childcnt;
214+ dest->children = &dest[1];
215+
216+ /* Push children to the stack
217+ * in a way where the first child ends up at the top of the
218+ * (downwards growing) stack, in order to be processed first. */
219+ stackTop -= dest->numchildren;
220+ for (i = 0, cn = dtd->scaffold[src_node].firstchild;
221+ i < dest->numchildren; i++, cn = dtd->scaffold[cn].nextsib) {
222+ (stackTop + i)->numchildren = (unsigned int)cn;
223+ }
224+ }
225+ }
226
227- build_node(parser, 0, ret, &cpos, &str);
228 return ret;
229 }
230
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25314.patch b/meta/recipes-core/expat/expat/CVE-2022-25314.patch
new file mode 100644
index 0000000000..2f713ebb54
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25314.patch
@@ -0,0 +1,32 @@
1From efcb347440ade24b9f1054671e6bd05e60b4cafd Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Tue, 15 Feb 2022 11:56:57 +0000
4Subject: [PATCH] Prevent integer overflow in copyString
5
6The copyString function is only used for encoding string supplied by
7the library user.
8
9Upstream-Status: Backport
10https://github.com/libexpat/libexpat/pull/560/commits/efcb347440ade24b9f1054671e6bd05e60b4cafd
11
12CVE: CVE-2022-25314
13
14Signed-off-by: Steve Sakoman <steve@sakoman.com>
15
16---
17 expat/lib/xmlparse.c | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/lib/xmlparse.c b/lib/xmlparse.c
21index 4b43e613..a39377c2 100644
22--- a/lib/xmlparse.c
23+++ b/lib/xmlparse.c
24@@ -7412,7 +7412,7 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
25
26 static XML_Char *
27 copyString(const XML_Char *s, const XML_Memory_Handling_Suite *memsuite) {
28- int charsRequired = 0;
29+ size_t charsRequired = 0;
30 XML_Char *result;
31
32 /* First determine how long the string is */
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25315.patch b/meta/recipes-core/expat/expat/CVE-2022-25315.patch
new file mode 100644
index 0000000000..a39771d28a
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25315.patch
@@ -0,0 +1,145 @@
1From eb0362808b4f9f1e2345a0cf203b8cc196d776d9 Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Tue, 15 Feb 2022 11:55:46 +0000
4Subject: [PATCH] Prevent integer overflow in storeRawNames
5
6It is possible to use an integer overflow in storeRawNames for out of
7boundary heap writes. Default configuration is affected. If compiled
8with XML_UNICODE then the attack does not work. Compiling with
9-fsanitize=address confirms the following proof of concept.
10
11The problem can be exploited by abusing the m_buffer expansion logic.
12Even though the initial size of m_buffer is a power of two, eventually
13it can end up a little bit lower, thus allowing allocations very close
14to INT_MAX (since INT_MAX/2 can be surpassed). This means that tag
15names can be parsed which are almost INT_MAX in size.
16
17Unfortunately (from an attacker point of view) INT_MAX/2 is also a
18limitation in string pools. Having a tag name of INT_MAX/2 characters
19or more is not possible.
20
21Expat can convert between different encodings. UTF-16 documents which
22contain only ASCII representable characters are twice as large as their
23ASCII encoded counter-parts.
24
25The proof of concept works by taking these three considerations into
26account:
27
281. Move the m_buffer size slightly below a power of two by having a
29 short root node <a>. This allows the m_buffer to grow very close
30 to INT_MAX.
312. The string pooling forbids tag names longer than or equal to
32 INT_MAX/2, so keep the attack tag name smaller than that.
333. To be able to still overflow INT_MAX even though the name is
34 limited at INT_MAX/2-1 (nul byte) we use UTF-16 encoding and a tag
35 which only contains ASCII characters. UTF-16 always stores two
36 bytes per character while the tag name is converted to using only
37 one. Our attack node byte count must be a bit higher than
38 2/3 INT_MAX so the converted tag name is around INT_MAX/3 which
39 in sum can overflow INT_MAX.
40
41Thanks to our small root node, m_buffer can handle 2/3 INT_MAX bytes
42without running into INT_MAX boundary check. The string pooling is
43able to store INT_MAX/3 as tag name because the amount is below
44INT_MAX/2 limitation. And creating the sum of both eventually overflows
45in storeRawNames.
46
47Proof of Concept:
48
491. Compile expat with -fsanitize=address.
50
512. Create Proof of Concept binary which iterates through input
52 file 16 MB at once for better performance and easier integer
53 calculations:
54
55```
56cat > poc.c << EOF
57 #include <err.h>
58 #include <expat.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61
62 #define CHUNK (16 * 1024 * 1024)
63 int main(int argc, char *argv[]) {
64 XML_Parser parser;
65 FILE *fp;
66 char *buf;
67 int i;
68
69 if (argc != 2)
70 errx(1, "usage: poc file.xml");
71 if ((parser = XML_ParserCreate(NULL)) == NULL)
72 errx(1, "failed to create expat parser");
73 if ((fp = fopen(argv[1], "r")) == NULL) {
74 XML_ParserFree(parser);
75 err(1, "failed to open file");
76 }
77 if ((buf = malloc(CHUNK)) == NULL) {
78 fclose(fp);
79 XML_ParserFree(parser);
80 err(1, "failed to allocate buffer");
81 }
82 i = 0;
83 while (fread(buf, CHUNK, 1, fp) == 1) {
84 printf("iteration %d: XML_Parse returns %d\n", ++i,
85 XML_Parse(parser, buf, CHUNK, XML_FALSE));
86 }
87 free(buf);
88 fclose(fp);
89 XML_ParserFree(parser);
90 return 0;
91 }
92EOF
93gcc -fsanitize=address -lexpat -o poc poc.c
94```
95
963. Construct specially prepared UTF-16 XML file:
97
98```
99dd if=/dev/zero bs=1024 count=794624 | tr '\0' 'a' > poc-utf8.xml
100echo -n '<a><' | dd conv=notrunc of=poc-utf8.xml
101echo -n '><' | dd conv=notrunc of=poc-utf8.xml bs=1 seek=805306368
102iconv -f UTF-8 -t UTF-16LE poc-utf8.xml > poc-utf16.xml
103```
104
1054. Run proof of concept:
106
107```
108./poc poc-utf16.xml
109```
110
111Upstream-Status: Backport
112https://github.com/libexpat/libexpat/pull/559/commits/eb0362808b4f9f1e2345a0cf203b8cc196d776d9
113
114CVE: CVE-2022-25315
115
116Signed-off-by: Steve Sakoman <steve@sakoman.com>
117---
118 lib/xmlparse.c | 7 ++++++-
119 1 file changed, 6 insertions(+), 1 deletion(-)
120
121diff --git a/lib/xmlparse.c b/lib/xmlparse.c
122index 4b43e613..f34d6ab5 100644
123--- a/lib/xmlparse.c
124+++ b/lib/xmlparse.c
125@@ -2563,6 +2563,7 @@ storeRawNames(XML_Parser parser) {
126 while (tag) {
127 int bufSize;
128 int nameLen = sizeof(XML_Char) * (tag->name.strLen + 1);
129+ size_t rawNameLen;
130 char *rawNameBuf = tag->buf + nameLen;
131 /* Stop if already stored. Since m_tagStack is a stack, we can stop
132 at the first entry that has already been copied; everything
133@@ -2574,7 +2575,11 @@ storeRawNames(XML_Parser parser) {
134 /* For re-use purposes we need to ensure that the
135 size of tag->buf is a multiple of sizeof(XML_Char).
136 */
137- bufSize = nameLen + ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
138+ rawNameLen = ROUND_UP(tag->rawNameLength, sizeof(XML_Char));
139+ /* Detect and prevent integer overflow. */
140+ if (rawNameLen > (size_t)INT_MAX - nameLen)
141+ return XML_FALSE;
142+ bufSize = nameLen + (int)rawNameLen;
143 if (bufSize > tag->bufEnd - tag->buf) {
144 char *temp = (char *)REALLOC(parser, tag->buf, bufSize);
145 if (temp == NULL)
diff --git a/meta/recipes-core/expat/expat/CVE-2022-40674.patch b/meta/recipes-core/expat/expat/CVE-2022-40674.patch
new file mode 100644
index 0000000000..8b95f5f198
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-40674.patch
@@ -0,0 +1,53 @@
1From 4a32da87e931ba54393d465bb77c40b5c33d343b Mon Sep 17 00:00:00 2001
2From: Rhodri James <rhodri@wildebeest.org.uk>
3Date: Wed, 17 Aug 2022 18:26:18 +0100
4Subject: [PATCH] Ensure raw tagnames are safe exiting internalEntityParser
5
6It is possible to concoct a situation in which parsing is
7suspended while substituting in an internal entity, so that
8XML_ResumeParser directly uses internalEntityProcessor as
9its processor. If the subsequent parse includes some unclosed
10tags, this will return without calling storeRawNames to ensure
11that the raw versions of the tag names are stored in memory other
12than the parse buffer itself. If the parse buffer is then changed
13or reallocated (for example if processing a file line by line),
14badness will ensue.
15
16This patch ensures storeRawNames is always called when needed
17after calling doContent. The earlier call do doContent does
18not need the same protection; it only deals with entity
19substitution, which cannot leave unbalanced tags, and in any
20case the raw names will be pointing into the stored entity
21value not the parse buffer.
22
23Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/4a32da87e931ba54393d465bb77c40b5c33d343b]
24CVE: CVE-2022-40674
25Signed-off-by: Virendra Thakur <virendrak@kpit.com>
26---
27 expat/lib/xmlparse.c | 13 +++++++++----
28 1 file changed, 9 insertions(+), 4 deletions(-)
29
30Index: expat/lib/xmlparse.c
31===================================================================
32--- a/lib/xmlparse.c
33+++ b/lib/xmlparse.c
34@@ -5657,10 +5657,15 @@ internalEntityProcessor(XML_Parser parse
35 {
36 parser->m_processor = contentProcessor;
37 /* see externalEntityContentProcessor vs contentProcessor */
38- return doContent(parser, parser->m_parentParser ? 1 : 0, parser->m_encoding,
39- s, end, nextPtr,
40- (XML_Bool)! parser->m_parsingStatus.finalBuffer,
41- XML_ACCOUNT_DIRECT);
42+ result = doContent(parser, parser->m_parentParser ? 1 : 0,
43+ parser->m_encoding, s, end, nextPtr,
44+ (XML_Bool)! parser->m_parsingStatus.finalBuffer,
45+ XML_ACCOUNT_DIRECT);
46+ if (result == XML_ERROR_NONE) {
47+ if (! storeRawNames(parser))
48+ return XML_ERROR_NO_MEMORY;
49+ }
50+ return result;
51 }
52 }
53
diff --git a/meta/recipes-core/expat/expat/CVE-2022-43680.patch b/meta/recipes-core/expat/expat/CVE-2022-43680.patch
new file mode 100644
index 0000000000..6f93bc3ed7
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-43680.patch
@@ -0,0 +1,33 @@
1From 5290462a7ea1278a8d5c0d5b2860d4e244f997e4 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Tue, 20 Sep 2022 02:44:34 +0200
4Subject: [PATCH] lib: Fix overeager DTD destruction in
5 XML_ExternalEntityParserCreate
6
7CVE: CVE-2022-43680
8Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/5290462a7ea1278a8d5c0d5b2860d4e244f997e4.patch]
9Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
10Comments: Hunk refreshed
11---
12 lib/xmlparse.c | 8 ++++++++
13 1 file changed, 8 insertions(+)
14
15diff --git a/lib/xmlparse.c b/lib/xmlparse.c
16index aacd6e7fc..57bf103cc 100644
17--- a/lib/xmlparse.c
18+++ b/lib/xmlparse.c
19@@ -1035,6 +1035,14 @@ parserCreate(const XML_Char *encodingNam
20 parserInit(parser, encodingName);
21
22 if (encodingName && ! parser->m_protocolEncodingName) {
23+ if (dtd) {
24+ // We need to stop the upcoming call to XML_ParserFree from happily
25+ // destroying parser->m_dtd because the DTD is shared with the parent
26+ // parser and the only guard that keeps XML_ParserFree from destroying
27+ // parser->m_dtd is parser->m_isParamEntity but it will be set to
28+ // XML_TRUE only later in XML_ExternalEntityParserCreate (or not at all).
29+ parser->m_dtd = NULL;
30+ }
31 XML_ParserFree(parser);
32 return NULL;
33 }
diff --git a/meta/recipes-core/expat/expat/libtool-tag.patch b/meta/recipes-core/expat/expat/libtool-tag.patch
index 0a0aed23e5..c59ccbbede 100644
--- a/meta/recipes-core/expat/expat/libtool-tag.patch
+++ b/meta/recipes-core/expat/expat/libtool-tag.patch
@@ -1,30 +1,27 @@
1From 10342e6b600858b091bc7771e454d9e06af06410 Mon Sep 17 00:00:00 2001 1From da433dbe79f2d4d5d7d79869c669594c99c5de9c Mon Sep 17 00:00:00 2001
2From: Khem Raj <raj.khem@gmail.com> 2From: Jasper Orschulko <jasper@fancydomain.eu>
3Date: Thu, 2 Nov 2017 18:20:57 +0800 3Date: Wed, 16 Jun 2021 19:00:30 +0200
4Subject: [PATCH] Add CC tag to build 4Subject: [PATCH] Add CC tag to build
5 5
6Add CC tag to build
7
8Upstream-Status: Pending 6Upstream-Status: Pending
9Signed-off-by: Khem Raj <raj.khem@gmail.com> 7Signed-off-by: Jasper Orschulko <jasper@fancydomain.eu>
10Signed-off-by: Dengke Du <dengke.du@windriver.com>
11--- 8---
12 Makefile.in | 2 +- 9 Makefile.am | 2 +-
13 1 file changed, 1 insertion(+), 1 deletion(-) 10 1 file changed, 1 insertion(+), 1 deletion(-)
14 11
15diff --git a/Makefile.in b/Makefile.in 12diff --git a/Makefile.am b/Makefile.am
16index 9560a95..d444bd6 100644 13index 5e1d37dd..f7a6dece 100644
17--- a/Makefile.in 14--- a/Makefile.am
18+++ b/Makefile.in 15+++ b/Makefile.am
19@@ -319,7 +319,7 @@ LIBCURRENT = @LIBCURRENT@ 16@@ -36,7 +36,7 @@ AUTOMAKE_OPTIONS = \
20 LIBOBJS = @LIBOBJS@ 17 subdir-objects
21 LIBREVISION = @LIBREVISION@ 18
22 LIBS = @LIBS@ 19 ACLOCAL_AMFLAGS = -I m4
23-LIBTOOL = @LIBTOOL@ 20-LIBTOOLFLAGS = --verbose
24+LIBTOOL = @LIBTOOL@ --tag CC 21+LIBTOOLFLAGS = --verbose --tag=CC
25 LIPO = @LIPO@ 22
26 LN_S = @LN_S@ 23 SUBDIRS = lib # lib goes first to build first
27 LTLIBOBJS = @LTLIBOBJS@ 24 if WITH_EXAMPLES
28-- 25--
292.7.4 262.32.0
30 27
diff --git a/meta/recipes-core/expat/expat_2.2.9.bb b/meta/recipes-core/expat/expat_2.2.9.bb
index 8f3db41352..8a5006e59a 100644
--- a/meta/recipes-core/expat/expat_2.2.9.bb
+++ b/meta/recipes-core/expat/expat_2.2.9.bb
@@ -1,22 +1,35 @@
1SUMMARY = "A stream-oriented XML parser library" 1SUMMARY = "A stream-oriented XML parser library"
2DESCRIPTION = "Expat is an XML parser library written in C. It is a stream-oriented parser in which an application registers handlers for things the parser might find in the XML document (like start tags)" 2DESCRIPTION = "Expat is an XML parser library written in C. It is a stream-oriented parser in which an application registers handlers for things the parser might find in the XML document (like start tags)"
3HOMEPAGE = "http://expat.sourceforge.net/" 3HOMEPAGE = "https://github.com/libexpat/libexpat"
4SECTION = "libs" 4SECTION = "libs"
5LICENSE = "MIT" 5LICENSE = "MIT"
6 6
7LIC_FILES_CHKSUM = "file://COPYING;md5=5b8620d98e49772d95fc1d291c26aa79" 7LIC_FILES_CHKSUM = "file://COPYING;md5=5b8620d98e49772d95fc1d291c26aa79"
8 8
9SRC_URI = "${SOURCEFORGE_MIRROR}/expat/expat-${PV}.tar.bz2 \ 9SRC_URI = "git://github.com/libexpat/libexpat.git;protocol=https;branch=master \
10 file://CVE-2013-0340.patch \
11 file://CVE-2021-45960.patch \
12 file://CVE-2021-46143.patch \
13 file://CVE-2022-22822-27.patch \
14 file://CVE-2022-23852.patch \
15 file://CVE-2022-23990.patch \
16 file://CVE-2022-25235.patch \
17 file://CVE-2022-25236.patch \
18 file://CVE-2022-25313.patch \
19 file://CVE-2022-25313-regression.patch \
20 file://CVE-2022-25314.patch \
21 file://CVE-2022-25315.patch \
10 file://libtool-tag.patch \ 22 file://libtool-tag.patch \
11 " 23 file://CVE-2022-40674.patch \
24 file://CVE-2022-43680.patch \
25 "
12 26
13SRC_URI[md5sum] = "875a2c2ff3e8eb9e5a5cd62db2033ab5" 27SRCREV = "a7bc26b69768f7fb24f0c7976fae24b157b85b13"
14SRC_URI[sha256sum] = "f1063084dc4302a427dabcca499c8312b3a32a29b7d2506653ecc8f950a9a237"
15 28
16inherit autotools lib_package 29inherit autotools lib_package
17 30
18do_configure_prepend () { 31S = "${WORKDIR}/git/expat"
19 rm -f ${S}/conftools/libtool.m4
20}
21 32
22BBCLASSEXTEND = "native nativesdk" 33BBCLASSEXTEND = "native nativesdk"
34
35CVE_PRODUCT = "expat libexpat"
diff --git a/meta/recipes-core/fts/fts_1.2.7.bb b/meta/recipes-core/fts/fts_1.2.7.bb
index 589ae0e916..d3b0f31eda 100644
--- a/meta/recipes-core/fts/fts_1.2.7.bb
+++ b/meta/recipes-core/fts/fts_1.2.7.bb
@@ -3,13 +3,14 @@
3 3
4SUMMARY = "Implementation of ftsfor musl libc packages" 4SUMMARY = "Implementation of ftsfor musl libc packages"
5HOMEPAGE = "https://github.com/pullmoll/musl-fts" 5HOMEPAGE = "https://github.com/pullmoll/musl-fts"
6DESCRIPTION = "The musl-fts package implements the fts(3) functions fts_open, fts_read, fts_children, fts_set and fts_close, which are missing in musl libc."
6LICENSE = "BSD-3-Clause" 7LICENSE = "BSD-3-Clause"
7LIC_FILES_CHKSUM = "file://COPYING;md5=5ffe358174aad383f1b69ce3b53da982" 8LIC_FILES_CHKSUM = "file://COPYING;md5=5ffe358174aad383f1b69ce3b53da982"
8SECTION = "libs" 9SECTION = "libs"
9 10
10SRCREV = "0bde52df588e8969879a2cae51c3a4774ec62472" 11SRCREV = "0bde52df588e8969879a2cae51c3a4774ec62472"
11 12
12SRC_URI = "git://github.com/pullmoll/musl-fts.git" 13SRC_URI = "git://github.com/pullmoll/musl-fts.git;branch=master;protocol=https"
13 14
14S = "${WORKDIR}/git" 15S = "${WORKDIR}/git"
15 16
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch
new file mode 100644
index 0000000000..6257763d8d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27218.patch
@@ -0,0 +1,129 @@
1Backport of:
2
3From 0f384c88a241bbbd884487b1c40b7b75f1e638d3 Mon Sep 17 00:00:00 2001
4From: Krzesimir Nowak <qdlacz@gmail.com>
5Date: Wed, 10 Feb 2021 23:51:07 +0100
6Subject: [PATCH] gbytearray: Do not accept too large byte arrays
7
8GByteArray uses guint for storing the length of the byte array, but it
9also has a constructor (g_byte_array_new_take) that takes length as a
10gsize. gsize may be larger than guint (64 bits for gsize vs 32 bits
11for guint). It is possible to call the function with a value greater
12than G_MAXUINT, which will result in silent length truncation. This
13may happen as a result of unreffing GBytes into GByteArray, so rather
14be loud about it.
15
16(Test case tweaked by Philip Withnall.)
17
18(Backport 2.66: Add #include gstrfuncsprivate.h in the test case for
19`g_memdup2()`.)
20
21Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
22CVE: CVE-2021-27218
23Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
24Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
25
26---
27 glib/garray.c | 6 ++++++
28 glib/gbytes.c | 4 ++++
29 glib/tests/bytes.c | 35 ++++++++++++++++++++++++++++++++++-
30 3 files changed, 44 insertions(+), 1 deletion(-)
31
32--- a/glib/garray.c
33+++ b/glib/garray.c
34@@ -2234,6 +2234,10 @@ g_byte_array_steal (GByteArray *array,
35 * Create byte array containing the data. The data will be owned by the array
36 * and will be freed with g_free(), i.e. it could be allocated using g_strdup().
37 *
38+ * Do not use it if @len is greater than %G_MAXUINT. #GByteArray
39+ * stores the length of its data in #guint, which may be shorter than
40+ * #gsize.
41+ *
42 * Since: 2.32
43 *
44 * Returns: (transfer full): a new #GByteArray
45@@ -2245,6 +2249,8 @@ g_byte_array_new_take (guint8 *data,
46 GByteArray *array;
47 GRealArray *real;
48
49+ g_return_val_if_fail (len <= G_MAXUINT, NULL);
50+
51 array = g_byte_array_new ();
52 real = (GRealArray *)array;
53 g_assert (real->data == NULL);
54--- a/glib/gbytes.c
55+++ b/glib/gbytes.c
56@@ -519,6 +519,10 @@ g_bytes_unref_to_data (GBytes *bytes,
57 * g_bytes_new(), g_bytes_new_take() or g_byte_array_free_to_bytes(). In all
58 * other cases the data is copied.
59 *
60+ * Do not use it if @bytes contains more than %G_MAXUINT
61+ * bytes. #GByteArray stores the length of its data in #guint, which
62+ * may be shorter than #gsize, that @bytes is using.
63+ *
64 * Returns: (transfer full): a new mutable #GByteArray containing the same byte data
65 *
66 * Since: 2.32
67--- a/glib/tests/bytes.c
68+++ b/glib/tests/bytes.c
69@@ -10,12 +10,12 @@
70 */
71
72 #undef G_DISABLE_ASSERT
73-#undef G_LOG_DOMAIN
74
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include "glib.h"
79+#include "glib/gstrfuncsprivate.h"
80
81 /* Keep in sync with glib/gbytes.c */
82 struct _GBytes
83@@ -334,6 +334,38 @@ test_to_array_transferred (void)
84 }
85
86 static void
87+test_to_array_transferred_oversize (void)
88+{
89+ g_test_message ("g_bytes_unref_to_array() can only take GBytes up to "
90+ "G_MAXUINT in length; test that longer ones are rejected");
91+
92+ if (sizeof (guint) >= sizeof (gsize))
93+ {
94+ g_test_skip ("Skipping test as guint is not smaller than gsize");
95+ }
96+ else if (g_test_undefined ())
97+ {
98+ GByteArray *array = NULL;
99+ GBytes *bytes = NULL;
100+ gpointer data = g_memdup2 (NYAN, N_NYAN);
101+ gsize len = ((gsize) G_MAXUINT) + 1;
102+
103+ bytes = g_bytes_new_take (data, len);
104+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
105+ "g_byte_array_new_take: assertion 'len <= G_MAXUINT' failed");
106+ array = g_bytes_unref_to_array (g_steal_pointer (&bytes));
107+ g_test_assert_expected_messages ();
108+ g_assert_null (array);
109+
110+ g_free (data);
111+ }
112+ else
113+ {
114+ g_test_skip ("Skipping test as testing undefined behaviour is disabled");
115+ }
116+}
117+
118+static void
119 test_to_array_two_refs (void)
120 {
121 gconstpointer memory;
122@@ -410,6 +442,7 @@ main (int argc, char *argv[])
123 g_test_add_func ("/bytes/to-array/transfered", test_to_array_transferred);
124 g_test_add_func ("/bytes/to-array/two-refs", test_to_array_two_refs);
125 g_test_add_func ("/bytes/to-array/non-malloc", test_to_array_non_malloc);
126+ g_test_add_func ("/bytes/to-array/transferred/oversize", test_to_array_transferred_oversize);
127 g_test_add_func ("/bytes/null", test_null);
128
129 return g_test_run ();
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch
new file mode 100644
index 0000000000..2af9dd6aa4
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-01.patch
@@ -0,0 +1,170 @@
1Backport of:
2
3From 5e5f75a77e399c638be66d74e5daa8caeb433e00 Mon Sep 17 00:00:00 2001
4From: Philip Withnall <pwithnall@endlessos.org>
5Date: Thu, 4 Feb 2021 13:30:52 +0000
6Subject: [PATCH 01/11] gstrfuncs: Add internal g_memdup2() function
7MIME-Version: 1.0
8Content-Type: text/plain; charset=UTF-8
9Content-Transfer-Encoding: 8bit
10
11This will replace the existing `g_memdup()` function for use within
12GLib. It has an unavoidable security flaw of taking its `byte_size`
13argument as a `guint` rather than as a `gsize`. Most callers will
14expect it to be a `gsize`, and may pass in large values which could
15silently be truncated, resulting in an undersize allocation compared
16to what the caller expects.
17
18This could lead to a classic buffer overflow vulnerability for many
19callers of `g_memdup()`.
20
21`g_memdup2()`, in comparison, takes its `byte_size` as a `gsize`.
22
23Spotted by Kevin Backhouse of GHSL.
24
25In GLib 2.68, `g_memdup2()` will be a new public API. In this version
26for backport to older stable releases, it’s a new `static inline` API
27in a private header, so that use of `g_memdup()` within GLib can be
28fixed without adding a new API in a stable release series.
29
30Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
31Helps: GHSL-2021-045
32Helps: #2319
33
34Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
35CVE: CVE-2021-27219
36Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
37Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
38
39---
40 docs/reference/glib/meson.build | 1 +
41 glib/gstrfuncsprivate.h | 55 +++++++++++++++++++++++++++++++++
42 glib/meson.build | 1 +
43 glib/tests/strfuncs.c | 23 ++++++++++++++
44 4 files changed, 80 insertions(+)
45 create mode 100644 glib/gstrfuncsprivate.h
46
47--- a/docs/reference/glib/meson.build
48+++ b/docs/reference/glib/meson.build
49@@ -22,6 +22,7 @@ if get_option('gtk_doc')
50 'gprintfint.h',
51 'gmirroringtable.h',
52 'gscripttable.h',
53+ 'gstrfuncsprivate.h',
54 'glib-mirroring-tab',
55 'gnulib',
56 'pcre',
57--- /dev/null
58+++ b/glib/gstrfuncsprivate.h
59@@ -0,0 +1,55 @@
60+/* GLIB - Library of useful routines for C programming
61+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
62+ *
63+ * This library is free software; you can redistribute it and/or
64+ * modify it under the terms of the GNU Lesser General Public
65+ * License as published by the Free Software Foundation; either
66+ * version 2.1 of the License, or (at your option) any later version.
67+ *
68+ * This library is distributed in the hope that it will be useful,
69+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
70+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
71+ * Lesser General Public License for more details.
72+ *
73+ * You should have received a copy of the GNU Lesser General Public
74+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
75+ */
76+
77+#include <glib.h>
78+#include <string.h>
79+
80+/*
81+ * g_memdup2:
82+ * @mem: (nullable): the memory to copy.
83+ * @byte_size: the number of bytes to copy.
84+ *
85+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
86+ * from @mem. If @mem is %NULL it returns %NULL.
87+ *
88+ * This replaces g_memdup(), which was prone to integer overflows when
89+ * converting the argument from a #gsize to a #guint.
90+ *
91+ * This static inline version is a backport of the new public API from
92+ * GLib 2.68, kept internal to GLib for backport to older stable releases.
93+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
94+ *
95+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
96+ * or %NULL if @mem is %NULL.
97+ * Since: 2.68
98+ */
99+static inline gpointer
100+g_memdup2 (gconstpointer mem,
101+ gsize byte_size)
102+{
103+ gpointer new_mem;
104+
105+ if (mem && byte_size != 0)
106+ {
107+ new_mem = g_malloc (byte_size);
108+ memcpy (new_mem, mem, byte_size);
109+ }
110+ else
111+ new_mem = NULL;
112+
113+ return new_mem;
114+}
115--- a/glib/meson.build
116+++ b/glib/meson.build
117@@ -268,6 +268,7 @@ glib_sources = files(
118 'gslist.c',
119 'gstdio.c',
120 'gstrfuncs.c',
121+ 'gstrfuncsprivate.h',
122 'gstring.c',
123 'gstringchunk.c',
124 'gtestutils.c',
125--- a/glib/tests/strfuncs.c
126+++ b/glib/tests/strfuncs.c
127@@ -32,6 +32,8 @@
128 #include <string.h>
129 #include "glib.h"
130
131+#include "gstrfuncsprivate.h"
132+
133 #if defined (_MSC_VER) && (_MSC_VER <= 1800)
134 #define isnan(x) _isnan(x)
135
136@@ -219,6 +221,26 @@ test_memdup (void)
137 g_free (str_dup);
138 }
139
140+/* Testing g_memdup2() function with various positive and negative cases */
141+static void
142+test_memdup2 (void)
143+{
144+ gchar *str_dup = NULL;
145+ const gchar *str = "The quick brown fox jumps over the lazy dog";
146+
147+ /* Testing negative cases */
148+ g_assert_null (g_memdup2 (NULL, 1024));
149+ g_assert_null (g_memdup2 (str, 0));
150+ g_assert_null (g_memdup2 (NULL, 0));
151+
152+ /* Testing normal usage cases */
153+ str_dup = g_memdup2 (str, strlen (str) + 1);
154+ g_assert_nonnull (str_dup);
155+ g_assert_cmpstr (str, ==, str_dup);
156+
157+ g_free (str_dup);
158+}
159+
160 /* Testing g_strpcpy() function with various positive and negative cases */
161 static void
162 test_stpcpy (void)
163@@ -2523,6 +2545,7 @@ main (int argc,
164 g_test_add_func ("/strfuncs/has-prefix", test_has_prefix);
165 g_test_add_func ("/strfuncs/has-suffix", test_has_suffix);
166 g_test_add_func ("/strfuncs/memdup", test_memdup);
167+ g_test_add_func ("/strfuncs/memdup2", test_memdup2);
168 g_test_add_func ("/strfuncs/stpcpy", test_stpcpy);
169 g_test_add_func ("/strfuncs/str_match_string", test_str_match_string);
170 g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch
new file mode 100644
index 0000000000..20137ea5f3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-02.patch
@@ -0,0 +1,249 @@
1From be8834340a2d928ece82025463ae23dee2c333d0 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 13:37:56 +0000
4Subject: [PATCH 02/11] gio: Use g_memdup2() instead of g_memdup() in obvious
5 places
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Convert all the call sites which use `g_memdup()`’s length argument
11trivially (for example, by passing a `sizeof()`), so that they use
12`g_memdup2()` instead.
13
14In almost all of these cases the use of `g_memdup()` would not have
15caused problems, but it will soon be deprecated, so best port away from
16it.
17
18Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
19Helps: #2319
20
21Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
22CVE: CVE-2021-27219
23Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
24Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
25
26---
27 gio/gdbusconnection.c | 5 +++--
28 gio/gdbusinterfaceskeleton.c | 3 ++-
29 gio/gfile.c | 7 ++++---
30 gio/gsettingsschema.c | 5 +++--
31 gio/gwin32registrykey.c | 8 +++++---
32 gio/tests/async-close-output-stream.c | 6 ++++--
33 gio/tests/gdbus-export.c | 5 +++--
34 gio/win32/gwinhttpfile.c | 9 +++++----
35 8 files changed, 29 insertions(+), 19 deletions(-)
36
37--- a/gio/gdbusconnection.c
38+++ b/gio/gdbusconnection.c
39@@ -110,6 +110,7 @@
40 #include "gasyncinitable.h"
41 #include "giostream.h"
42 #include "gasyncresult.h"
43+#include "gstrfuncsprivate.h"
44 #include "gtask.h"
45 #include "gmarshal-internal.h"
46
47@@ -4007,7 +4008,7 @@ _g_dbus_interface_vtable_copy (const GDB
48 /* Don't waste memory by copying padding - remember to update this
49 * when changing struct _GDBusInterfaceVTable in gdbusconnection.h
50 */
51- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
52+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
53 }
54
55 static void
56@@ -4024,7 +4025,7 @@ _g_dbus_subtree_vtable_copy (const GDBus
57 /* Don't waste memory by copying padding - remember to update this
58 * when changing struct _GDBusSubtreeVTable in gdbusconnection.h
59 */
60- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer));
61+ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer));
62 }
63
64 static void
65--- a/gio/gdbusinterfaceskeleton.c
66+++ b/gio/gdbusinterfaceskeleton.c
67@@ -28,6 +28,7 @@
68 #include "gdbusmethodinvocation.h"
69 #include "gdbusconnection.h"
70 #include "gmarshal-internal.h"
71+#include "gstrfuncsprivate.h"
72 #include "gtask.h"
73 #include "gioerror.h"
74
75@@ -701,7 +702,7 @@ add_connection_locked (GDBusInterfaceSke
76 * properly before building the hooked_vtable, so we create it
77 * once at the last minute.
78 */
79- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
80+ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable));
81 interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call;
82 }
83
84--- a/gio/gfile.c
85+++ b/gio/gfile.c
86@@ -60,6 +60,7 @@
87 #include "gasyncresult.h"
88 #include "gioerror.h"
89 #include "glibintl.h"
90+#include "gstrfuncsprivate.h"
91
92
93 /**
94@@ -7854,7 +7855,7 @@ measure_disk_usage_progress (gboolean re
95 g_main_context_invoke_full (g_task_get_context (task),
96 g_task_get_priority (task),
97 measure_disk_usage_invoke_progress,
98- g_memdup (&progress, sizeof progress),
99+ g_memdup2 (&progress, sizeof progress),
100 g_free);
101 }
102
103@@ -7872,7 +7873,7 @@ measure_disk_usage_thread (GTask
104 data->progress_callback ? measure_disk_usage_progress : NULL, task,
105 &result.disk_usage, &result.num_dirs, &result.num_files,
106 &error))
107- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free);
108+ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free);
109 else
110 g_task_return_error (task, error);
111 }
112@@ -7896,7 +7897,7 @@ g_file_real_measure_disk_usage_async (GF
113
114 task = g_task_new (file, cancellable, callback, user_data);
115 g_task_set_source_tag (task, g_file_real_measure_disk_usage_async);
116- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free);
117+ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free);
118 g_task_set_priority (task, io_priority);
119
120 g_task_run_in_thread (task, measure_disk_usage_thread);
121--- a/gio/gsettingsschema.c
122+++ b/gio/gsettingsschema.c
123@@ -20,6 +20,7 @@
124
125 #include "gsettingsschema-internal.h"
126 #include "gsettings.h"
127+#include "gstrfuncsprivate.h"
128
129 #include "gvdb/gvdb-reader.h"
130 #include "strinfo.c"
131@@ -1067,9 +1068,9 @@ g_settings_schema_list_children (GSettin
132
133 if (g_str_has_suffix (key, "/"))
134 {
135- gint length = strlen (key);
136+ gsize length = strlen (key);
137
138- strv[j] = g_memdup (key, length);
139+ strv[j] = g_memdup2 (key, length);
140 strv[j][length - 1] = '\0';
141 j++;
142 }
143--- a/gio/gwin32registrykey.c
144+++ b/gio/gwin32registrykey.c
145@@ -28,6 +28,8 @@
146 #include <ntstatus.h>
147 #include <winternl.h>
148
149+#include "gstrfuncsprivate.h"
150+
151 #ifndef _WDMDDK_
152 typedef enum _KEY_INFORMATION_CLASS {
153 KeyBasicInformation,
154@@ -247,7 +249,7 @@ g_win32_registry_value_iter_copy (const
155 new_iter->value_name_size = iter->value_name_size;
156
157 if (iter->value_data != NULL)
158- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size);
159+ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size);
160
161 new_iter->value_data_size = iter->value_data_size;
162
163@@ -268,8 +270,8 @@ g_win32_registry_value_iter_copy (const
164 new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize;
165
166 if (iter->value_data_expanded_u8 != NULL)
167- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8,
168- iter->value_data_expanded_charsize);
169+ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8,
170+ iter->value_data_expanded_charsize);
171
172 new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize;
173
174--- a/gio/tests/async-close-output-stream.c
175+++ b/gio/tests/async-close-output-stream.c
176@@ -24,6 +24,8 @@
177 #include <stdlib.h>
178 #include <string.h>
179
180+#include "gstrfuncsprivate.h"
181+
182 #define DATA_TO_WRITE "Hello world\n"
183
184 typedef struct
185@@ -147,9 +149,9 @@ prepare_data (SetupData *data,
186
187 data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream));
188
189- g_assert_cmpint (data->expected_size, >, 0);
190+ g_assert_cmpuint (data->expected_size, >, 0);
191
192- data->expected_output = g_memdup (written, (guint)data->expected_size);
193+ data->expected_output = g_memdup2 (written, data->expected_size);
194
195 /* then recreate the streams and prepare them for the asynchronous close */
196 destroy_streams (data);
197--- a/gio/tests/gdbus-export.c
198+++ b/gio/tests/gdbus-export.c
199@@ -23,6 +23,7 @@
200 #include <string.h>
201
202 #include "gdbus-tests.h"
203+#include "gstrfuncsprivate.h"
204
205 /* all tests rely on a shared mainloop */
206 static GMainLoop *loop = NULL;
207@@ -671,7 +672,7 @@ subtree_introspect (GDBusConnection
208 g_assert_not_reached ();
209 }
210
211- return g_memdup (interfaces, 2 * sizeof (void *));
212+ return g_memdup2 (interfaces, 2 * sizeof (void *));
213 }
214
215 static const GDBusInterfaceVTable *
216@@ -727,7 +728,7 @@ dynamic_subtree_introspect (GDBusConnect
217 {
218 const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL };
219
220- return g_memdup (interfaces, 2 * sizeof (void *));
221+ return g_memdup2 (interfaces, 2 * sizeof (void *));
222 }
223
224 static const GDBusInterfaceVTable *
225--- a/gio/win32/gwinhttpfile.c
226+++ b/gio/win32/gwinhttpfile.c
227@@ -29,6 +29,7 @@
228 #include "gio/gfile.h"
229 #include "gio/gfileattribute.h"
230 #include "gio/gfileinfo.h"
231+#include "gstrfuncsprivate.h"
232 #include "gwinhttpfile.h"
233 #include "gwinhttpfileinputstream.h"
234 #include "gwinhttpfileoutputstream.h"
235@@ -393,10 +394,10 @@
236 child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
237 child->vfs = winhttp_file->vfs;
238 child->url = winhttp_file->url;
239- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
240- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
241- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
242- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
243+ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
244+ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
245+ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
246+ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
247 child->url.lpszUrlPath = wnew_path;
248 child->url.dwUrlPathLength = wcslen (wnew_path);
249 child->url.lpszExtraInfo = NULL;
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch
new file mode 100644
index 0000000000..eceff161a6
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-03.patch
@@ -0,0 +1,131 @@
1From 6110caea45b235420b98cd41d845cc92238f6781 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 13:39:25 +0000
4Subject: [PATCH 03/11] gobject: Use g_memdup2() instead of g_memdup() in
5 obvious places
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Convert all the call sites which use `g_memdup()`’s length argument
11trivially (for example, by passing a `sizeof()`), so that they use
12`g_memdup2()` instead.
13
14In almost all of these cases the use of `g_memdup()` would not have
15caused problems, but it will soon be deprecated, so best port away from
16it.
17
18Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
19Helps: #2319
20
21Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
22CVE: CVE-2021-27219
23Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
24Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
25
26---
27 gobject/gsignal.c | 3 ++-
28 gobject/gtype.c | 9 +++++----
29 gobject/gtypemodule.c | 3 ++-
30 gobject/tests/param.c | 4 +++-
31 4 files changed, 12 insertions(+), 7 deletions(-)
32
33--- a/gobject/gsignal.c
34+++ b/gobject/gsignal.c
35@@ -28,6 +28,7 @@
36 #include <signal.h>
37
38 #include "gsignal.h"
39+#include "gstrfuncsprivate.h"
40 #include "gtype-private.h"
41 #include "gbsearcharray.h"
42 #include "gvaluecollector.h"
43@@ -1809,7 +1810,7 @@ g_signal_newv (const gchar *signal
44 node->single_va_closure_is_valid = FALSE;
45 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
46 node->n_params = n_params;
47- node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
48+ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
49 node->return_type = return_type;
50 node->class_closure_bsa = NULL;
51 if (accumulator)
52--- a/gobject/gtype.c
53+++ b/gobject/gtype.c
54@@ -33,6 +33,7 @@
55
56 #include "glib-private.h"
57 #include "gconstructor.h"
58+#include "gstrfuncsprivate.h"
59
60 #ifdef G_OS_WIN32
61 #include <windows.h>
62@@ -1470,7 +1471,7 @@ type_add_interface_Wm (TypeNode
63 iholder->next = iface_node_get_holders_L (iface);
64 iface_node_set_holders_W (iface, iholder);
65 iholder->instance_type = NODE_TYPE (node);
66- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
67+ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
68 iholder->plugin = plugin;
69
70 /* create an iface entry for this type */
71@@ -1731,7 +1732,7 @@ type_iface_retrieve_holder_info_Wm (Type
72 INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
73
74 check_interface_info_I (iface, instance_type, &tmp_info);
75- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
76+ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
77 }
78
79 return iholder; /* we don't modify write lock upon returning NULL */
80@@ -2016,10 +2017,10 @@ type_iface_vtable_base_init_Wm (TypeNode
81 IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
82
83 if (pentry)
84- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
85+ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
86 }
87 if (!vtable)
88- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
89+ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
90 entry->vtable = vtable;
91 vtable->g_type = NODE_TYPE (iface);
92 vtable->g_instance_type = NODE_TYPE (node);
93--- a/gobject/gtypemodule.c
94+++ b/gobject/gtypemodule.c
95@@ -19,6 +19,7 @@
96
97 #include <stdlib.h>
98
99+#include "gstrfuncsprivate.h"
100 #include "gtypeplugin.h"
101 #include "gtypemodule.h"
102
103@@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule
104 module_type_info->loaded = TRUE;
105 module_type_info->info = *type_info;
106 if (type_info->value_table)
107- module_type_info->info.value_table = g_memdup (type_info->value_table,
108+ module_type_info->info.value_table = g_memdup2 (type_info->value_table,
109 sizeof (GTypeValueTable));
110
111 return module_type_info->type;
112--- a/gobject/tests/param.c
113+++ b/gobject/tests/param.c
114@@ -2,6 +2,8 @@
115 #include <glib-object.h>
116 #include <stdlib.h>
117
118+#include "gstrfuncsprivate.h"
119+
120 static void
121 test_param_value (void)
122 {
123@@ -874,7 +876,7 @@ main (int argc, char *argv[])
124 test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
125 data.change_this_flag, data.change_this_type,
126 data.use_this_flag, data.use_this_type);
127- test_data = g_memdup (&data, sizeof (TestParamImplementData));
128+ test_data = g_memdup2 (&data, sizeof (TestParamImplementData));
129 g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
130 g_free (test_path);
131 }
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch
new file mode 100644
index 0000000000..6a3ac6b552
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-04.patch
@@ -0,0 +1,298 @@
1Backport of:
2
3From 0736b7c1e7cf4232c5d7eb2b0fbfe9be81bd3baa Mon Sep 17 00:00:00 2001
4From: Philip Withnall <pwithnall@endlessos.org>
5Date: Thu, 4 Feb 2021 13:41:21 +0000
6Subject: [PATCH 04/11] glib: Use g_memdup2() instead of g_memdup() in obvious
7 places
8MIME-Version: 1.0
9Content-Type: text/plain; charset=UTF-8
10Content-Transfer-Encoding: 8bit
11
12Convert all the call sites which use `g_memdup()`’s length argument
13trivially (for example, by passing a `sizeof()` or an existing `gsize`
14variable), so that they use `g_memdup2()` instead.
15
16In almost all of these cases the use of `g_memdup()` would not have
17caused problems, but it will soon be deprecated, so best port away from
18it
19
20In particular, this fixes an overflow within `g_bytes_new()`, identified
21as GHSL-2021-045 by GHSL team member Kevin Backhouse.
22
23Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
24Fixes: GHSL-2021-045
25Helps: #2319
26
27Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
28CVE: CVE-2021-27219
29Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
30Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
31
32---
33 glib/gbytes.c | 6 ++++--
34 glib/gdir.c | 3 ++-
35 glib/ghash.c | 7 ++++---
36 glib/giochannel.c | 5 +++--
37 glib/gslice.c | 3 ++-
38 glib/gtestutils.c | 3 ++-
39 glib/gvariant.c | 7 ++++---
40 glib/gvarianttype.c | 3 ++-
41 glib/tests/array-test.c | 4 +++-
42 glib/tests/option-context.c | 6 ++++--
43 glib/tests/uri.c | 8 +++++---
44 11 files changed, 35 insertions(+), 20 deletions(-)
45
46--- a/glib/gbytes.c
47+++ b/glib/gbytes.c
48@@ -34,6 +34,8 @@
49
50 #include <string.h>
51
52+#include "gstrfuncsprivate.h"
53+
54 /**
55 * GBytes:
56 *
57@@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data,
58 {
59 g_return_val_if_fail (data != NULL || size == 0, NULL);
60
61- return g_bytes_new_take (g_memdup (data, size), size);
62+ return g_bytes_new_take (g_memdup2 (data, size), size);
63 }
64
65 /**
66@@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes,
67 * Copy: Non g_malloc (or compatible) allocator, or static memory,
68 * so we have to copy, and then unref.
69 */
70- result = g_memdup (bytes->data, bytes->size);
71+ result = g_memdup2 (bytes->data, bytes->size);
72 *size = bytes->size;
73 g_bytes_unref (bytes);
74 }
75--- a/glib/gdir.c
76+++ b/glib/gdir.c
77@@ -37,6 +37,7 @@
78 #include "gconvert.h"
79 #include "gfileutils.h"
80 #include "gstrfuncs.h"
81+#include "gstrfuncsprivate.h"
82 #include "gtestutils.h"
83 #include "glibintl.h"
84
85@@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path
86 return NULL;
87 #endif
88
89- return g_memdup (&dir, sizeof dir);
90+ return g_memdup2 (&dir, sizeof dir);
91 }
92
93 /**
94--- a/glib/ghash.c
95+++ b/glib/ghash.c
96@@ -34,6 +34,7 @@
97 #include "gmacros.h"
98 #include "glib-private.h"
99 #include "gstrfuncs.h"
100+#include "gstrfuncsprivate.h"
101 #include "gatomic.h"
102 #include "gtestutils.h"
103 #include "gslice.h"
104@@ -962,7 +963,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
105 if (hash_table->have_big_keys)
106 {
107 if (key != value)
108- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
109+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
110 /* Keys and values are both big now, so no need for further checks */
111 return;
112 }
113@@ -970,7 +971,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
114 {
115 if (key != value)
116 {
117- hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size);
118+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size);
119 is_a_set = FALSE;
120 }
121 }
122@@ -998,7 +999,7 @@ g_hash_table_ensure_keyval_fits (GHashTa
123
124 /* Just split if necessary */
125 if (is_a_set && key != value)
126- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size);
127+ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size);
128
129 #endif
130 }
131--- a/glib/giochannel.c
132+++ b/glib/giochannel.c
133@@ -35,7 +35,7 @@
134 #include <errno.h>
135
136 #include "giochannel.h"
137-
138+#include "gstrfuncsprivate.h"
139 #include "gstrfuncs.h"
140 #include "gtestutils.h"
141 #include "glibintl.h"
142
143@@ -1673,10 +1674,10 @@ g_io_channel_read_line (GIOChannel *cha
144
145 /* Copy the read bytes (including any embedded nuls) and nul-terminate.
146 * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a
147- * #GString, so it’s safe to call g_memdup() with +1 length to allocate
148+ * #GString, so it’s safe to call g_memdup2() with +1 length to allocate
149 * a nul-terminator. */
150 g_assert (USE_BUF (channel));
151- line = g_memdup (USE_BUF (channel)->str, got_length + 1);
152+ line = g_memdup2 (USE_BUF (channel)->str, got_length + 1);
153 line[got_length] = '\0';
154 *str_return = g_steal_pointer (&line);
155 g_string_erase (USE_BUF (channel), 0, got_length);
156--- a/glib/gslice.c
157+++ b/glib/gslice.c
158@@ -41,6 +41,7 @@
159 #include "gmain.h"
160 #include "gmem.h" /* gslice.h */
161 #include "gstrfuncs.h"
162+#include "gstrfuncsprivate.h"
163 #include "gutils.h"
164 #include "gtrashstack.h"
165 #include "gtestutils.h"
166@@ -350,7 +351,7 @@ g_slice_get_config_state (GSliceConfig c
167 array[i++] = allocator->contention_counters[address];
168 array[i++] = allocator_get_magazine_threshold (allocator, address);
169 *n_values = i;
170- return g_memdup (array, sizeof (array[0]) * *n_values);
171+ return g_memdup2 (array, sizeof (array[0]) * *n_values);
172 default:
173 return NULL;
174 }
175--- a/glib/gtestutils.c
176+++ b/glib/gtestutils.c
177@@ -49,6 +49,7 @@
178 #include "gpattern.h"
179 #include "grand.h"
180 #include "gstrfuncs.h"
181+#include "gstrfuncsprivate.h"
182 #include "gtimer.h"
183 #include "gslice.h"
184 #include "gspawn.h"
185@@ -3803,7 +3804,7 @@ g_test_log_extract (GTestLogBuffer *tbuf
186 if (p <= tbuffer->data->str + mlength)
187 {
188 g_string_erase (tbuffer->data, 0, mlength);
189- tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg)));
190+ tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg)));
191 return TRUE;
192 }
193
194--- a/glib/gvariant.c
195+++ b/glib/gvariant.c
196@@ -33,6 +33,7 @@
197
198 #include <string.h>
199
200+#include "gstrfuncsprivate.h"
201
202 /**
203 * SECTION:gvariant
204@@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value)
205 g_variant_ref_sink (value);
206
207 return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
208- g_memdup (&value, sizeof value),
209+ g_memdup2 (&value, sizeof value),
210 1, g_variant_is_trusted (value));
211 }
212
213@@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVarian
214 return NULL;
215 }
216
217- data = g_memdup (elements, n_elements * element_size);
218+ data = g_memdup2 (elements, n_elements * element_size);
219 value = g_variant_new_from_data (array_type, data,
220 n_elements * element_size,
221 FALSE, g_free, data);
222@@ -1908,7 +1909,7 @@ g_variant_dup_bytestring (GVariant *valu
223 if (length)
224 *length = size;
225
226- return g_memdup (original, size + 1);
227+ return g_memdup2 (original, size + 1);
228 }
229
230 /**
231--- a/glib/gvarianttype.c
232+++ b/glib/gvarianttype.c
233@@ -28,6 +28,7 @@
234
235 #include <string.h>
236
237+#include "gstrfuncsprivate.h"
238
239 /**
240 * SECTION:gvarianttype
241@@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariant
242 g_assert (offset < sizeof buffer);
243 buffer[offset++] = ')';
244
245- return (GVariantType *) g_memdup (buffer, offset);
246+ return (GVariantType *) g_memdup2 (buffer, offset);
247 }
248
249 /**
250--- a/glib/tests/array-test.c
251+++ b/glib/tests/array-test.c
252@@ -29,6 +29,8 @@
253 #include <string.h>
254 #include "glib.h"
255
256+#include "gstrfuncsprivate.h"
257+
258 /* Test data to be passed to any function which calls g_array_new(), providing
259 * the parameters for that call. Most #GArray tests should be repeated for all
260 * possible values of #ArrayTestData. */
261@@ -1917,7 +1919,7 @@ byte_array_new_take (void)
262 GByteArray *gbarray;
263 guint8 *data;
264
265- data = g_memdup ("woooweeewow", 11);
266+ data = g_memdup2 ("woooweeewow", 11);
267 gbarray = g_byte_array_new_take (data, 11);
268 g_assert (gbarray->data == data);
269 g_assert_cmpuint (gbarray->len, ==, 11);
270--- a/glib/tests/option-context.c
271+++ b/glib/tests/option-context.c
272@@ -27,6 +27,8 @@
273 #include <string.h>
274 #include <locale.h>
275
276+#include "gstrfuncsprivate.h"
277+
278 static GOptionEntry main_entries[] = {
279 { "main-switch", 0, 0,
280 G_OPTION_ARG_NONE, NULL,
281@@ -256,7 +258,7 @@ join_stringv (int argc, char **argv)
282 static char **
283 copy_stringv (char **argv, int argc)
284 {
285- return g_memdup (argv, sizeof (char *) * (argc + 1));
286+ return g_memdup2 (argv, sizeof (char *) * (argc + 1));
287 }
288
289 static void
290@@ -2323,7 +2325,7 @@ test_group_parse (void)
291 g_option_context_add_group (context, group);
292
293 argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc);
294- orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *));
295+ orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *));
296
297 retval = g_option_context_parse (context, &argc, &argv, &error);
298
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch
new file mode 100644
index 0000000000..4f86522d00
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-05.patch
@@ -0,0 +1,54 @@
1From 0cbad673215ec8a049b7fe2ff44b0beed31b376e Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 16:12:24 +0000
4Subject: [PATCH 05/11] gwinhttpfile: Avoid arithmetic overflow when
5 calculating a size
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10The members of `URL_COMPONENTS` (`winhttp_file->url`) are `DWORD`s, i.e.
1132-bit unsigned integers. Adding to and multiplying them may cause them
12to overflow the unsigned integer bounds, even if the result is passed to
13`g_memdup2()` which accepts a `gsize`.
14
15Cast the `URL_COMPONENTS` members to `gsize` first to ensure that the
16arithmetic is done in terms of `gsize`s rather than unsigned integers.
17
18Spotted by Sebastian Dröge.
19
20Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
21Helps: #2319
22
23Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
24CVE: CVE-2021-27219
25Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
26Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
27
28---
29 gio/win32/gwinhttpfile.c | 8 ++++----
30 1 file changed, 4 insertions(+), 4 deletions(-)
31
32diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c
33index 3f8fbd838..e0340e247 100644
34--- a/gio/win32/gwinhttpfile.c
35+++ b/gio/win32/gwinhttpfile.c
36@@ -410,10 +410,10 @@ g_winhttp_file_resolve_relative_path (GFile *file,
37 child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
38 child->vfs = winhttp_file->vfs;
39 child->url = winhttp_file->url;
40- child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2);
41- child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2);
42- child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2);
43- child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2);
44+ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
45+ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
46+ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
47+ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
48 child->url.lpszUrlPath = wnew_path;
49 child->url.dwUrlPathLength = wcslen (wnew_path);
50 child->url.lpszExtraInfo = NULL;
51--
52GitLab
53
54
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch
new file mode 100644
index 0000000000..d8043f5e29
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-06.patch
@@ -0,0 +1,101 @@
1From f9ee2275cbc312c0b4cdbc338a4fbb76eb36fb9a Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 13:49:00 +0000
4Subject: [PATCH 06/11] gdatainputstream: Handle stop_chars_len internally as
5 gsize
6
7Previously it was handled as a `gssize`, which meant that if the
8`stop_chars` string was longer than `G_MAXSSIZE` there would be an
9overflow.
10
11Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
12Helps: #2319
13
14Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
15CVE: CVE-2021-27219
16Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
17Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
18
19---
20 gio/gdatainputstream.c | 25 +++++++++++++++++--------
21 1 file changed, 17 insertions(+), 8 deletions(-)
22
23diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c
24index 2e7750cb5..2cdcbda19 100644
25--- a/gio/gdatainputstream.c
26+++ b/gio/gdatainputstream.c
27@@ -27,6 +27,7 @@
28 #include "gioenumtypes.h"
29 #include "gioerror.h"
30 #include "glibintl.h"
31+#include "gstrfuncsprivate.h"
32
33 #include <string.h>
34
35@@ -856,7 +857,7 @@ static gssize
36 scan_for_chars (GDataInputStream *stream,
37 gsize *checked_out,
38 const char *stop_chars,
39- gssize stop_chars_len)
40+ gsize stop_chars_len)
41 {
42 GBufferedInputStream *bstream;
43 const char *buffer;
44@@ -952,7 +953,7 @@ typedef struct
45 gsize checked;
46
47 gchar *stop_chars;
48- gssize stop_chars_len;
49+ gsize stop_chars_len;
50 gsize length;
51 } GDataInputStreamReadData;
52
53@@ -1078,12 +1079,17 @@ g_data_input_stream_read_async (GDataInputStream *stream,
54 {
55 GDataInputStreamReadData *data;
56 GTask *task;
57+ gsize stop_chars_len_unsigned;
58
59 data = g_slice_new0 (GDataInputStreamReadData);
60- if (stop_chars_len == -1)
61- stop_chars_len = strlen (stop_chars);
62- data->stop_chars = g_memdup (stop_chars, stop_chars_len);
63- data->stop_chars_len = stop_chars_len;
64+
65+ if (stop_chars_len < 0)
66+ stop_chars_len_unsigned = strlen (stop_chars);
67+ else
68+ stop_chars_len_unsigned = (gsize) stop_chars_len;
69+
70+ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
71+ data->stop_chars_len = stop_chars_len_unsigned;
72 data->last_saw_cr = FALSE;
73
74 task = g_task_new (stream, cancellable, callback, user_data);
75@@ -1338,17 +1344,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream,
76 gssize found_pos;
77 gssize res;
78 char *data_until;
79+ gsize stop_chars_len_unsigned;
80
81 g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
82
83 if (stop_chars_len < 0)
84- stop_chars_len = strlen (stop_chars);
85+ stop_chars_len_unsigned = strlen (stop_chars);
86+ else
87+ stop_chars_len_unsigned = (gsize) stop_chars_len;
88
89 bstream = G_BUFFERED_INPUT_STREAM (stream);
90
91 checked = 0;
92
93- while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1)
94+ while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
95 {
96 if (g_buffered_input_stream_get_available (bstream) ==
97 g_buffered_input_stream_get_buffer_size (bstream))
98--
99GitLab
100
101
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch
new file mode 100644
index 0000000000..f183939c45
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-07.patch
@@ -0,0 +1,76 @@
1From 2aaf593a9eb96d84fe3be740aca2810a97d95592 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 13:50:37 +0000
4Subject: [PATCH 07/11] gwin32: Use gsize internally in g_wcsdup()
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9This allows it to handle strings up to length `G_MAXSIZE` — previously
10it would overflow with such strings.
11
12Update the several copies of it identically.
13
14Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
15Helps: #2319
16
17Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
18CVE: CVE-2021-27219
19Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
20Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
21
22---
23 gio/gwin32registrykey.c | 34 ++++++++++++++++++++++++++--------
24 2 files changed, 38 insertions(+), 16 deletions(-)
25
26diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c
27index 548a94188..2eb67daf8 100644
28--- a/gio/gwin32registrykey.c
29+++ b/gio/gwin32registrykey.c
30@@ -127,16 +127,34 @@ typedef enum
31 G_WIN32_REGISTRY_UPDATED_PATH = 1,
32 } GWin32RegistryKeyUpdateFlag;
33
34+static gsize
35+g_utf16_len (const gunichar2 *str)
36+{
37+ gsize result;
38+
39+ for (result = 0; str[0] != 0; str++, result++)
40+ ;
41+
42+ return result;
43+}
44+
45 static gunichar2 *
46-g_wcsdup (const gunichar2 *str,
47- gssize str_size)
48+g_wcsdup (const gunichar2 *str, gssize str_len)
49 {
50- if (str_size == -1)
51- {
52- str_size = wcslen (str) + 1;
53- str_size *= sizeof (gunichar2);
54- }
55- return g_memdup (str, str_size);
56+ gsize str_len_unsigned;
57+ gsize str_size;
58+
59+ g_return_val_if_fail (str != NULL, NULL);
60+
61+ if (str_len < 0)
62+ str_len_unsigned = g_utf16_len (str);
63+ else
64+ str_len_unsigned = (gsize) str_len;
65+
66+ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1);
67+ str_size = (str_len_unsigned + 1) * sizeof (gunichar2);
68+
69+ return g_memdup2 (str, str_size);
70 }
71
72 /**
73--
74GitLab
75
76
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch
new file mode 100644
index 0000000000..ffafc35c07
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-08.patch
@@ -0,0 +1,101 @@
1From ba8ca443051f93a74c0d03d62e70402036f967a5 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 13:58:32 +0000
4Subject: [PATCH 08/11] gkeyfilesettingsbackend: Handle long keys when
5 converting paths
6
7Previously, the code in `convert_path()` could not handle keys longer
8than `G_MAXINT`, and would overflow if that was exceeded.
9
10Convert the code to use `gsize` and `g_memdup2()` throughout, and
11change from identifying the position of the final slash in the string
12using a signed offset `i`, to using a pointer to the character (and
13`strrchr()`). This allows the slash to be at any position in a
14`G_MAXSIZE`-long string, without sacrificing a bit of the offset for
15indicating whether a slash was found.
16
17Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
18Helps: #2319
19
20Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
21CVE: CVE-2021-27219
22Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
23Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
24
25---
26 gio/gkeyfilesettingsbackend.c | 21 ++++++++++-----------
27 1 file changed, 10 insertions(+), 11 deletions(-)
28
29diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
30index cd5765afd..25b057672 100644
31--- a/gio/gkeyfilesettingsbackend.c
32+++ b/gio/gkeyfilesettingsbackend.c
33@@ -33,6 +33,7 @@
34 #include "gfilemonitor.h"
35 #include "gsimplepermission.h"
36 #include "gsettingsbackendinternal.h"
37+#include "gstrfuncsprivate.h"
38 #include "giomodule-priv.h"
39 #include "gportalsupport.h"
40
41@@ -145,8 +146,8 @@ convert_path (GKeyfileSettingsBackend *kfsb,
42 gchar **group,
43 gchar **basename)
44 {
45- gint key_len = strlen (key);
46- gint i;
47+ gsize key_len = strlen (key);
48+ const gchar *last_slash;
49
50 if (key_len < kfsb->prefix_len ||
51 memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0)
52@@ -155,38 +156,36 @@ convert_path (GKeyfileSettingsBackend *kfsb,
53 key_len -= kfsb->prefix_len;
54 key += kfsb->prefix_len;
55
56- for (i = key_len; i >= 0; i--)
57- if (key[i] == '/')
58- break;
59+ last_slash = strrchr (key, '/');
60
61 if (kfsb->root_group)
62 {
63 /* if a root_group was specified, make sure the user hasn't given
64 * a path that ghosts that group name
65 */
66- if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0)
67+ if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0)
68 return FALSE;
69 }
70 else
71 {
72 /* if no root_group was given, ensure that the user gave a path */
73- if (i == -1)
74+ if (last_slash == NULL)
75 return FALSE;
76 }
77
78 if (group)
79 {
80- if (i >= 0)
81+ if (last_slash != NULL)
82 {
83- *group = g_memdup (key, i + 1);
84- (*group)[i] = '\0';
85+ *group = g_memdup2 (key, (last_slash - key) + 1);
86+ (*group)[(last_slash - key)] = '\0';
87 }
88 else
89 *group = g_strdup (kfsb->root_group);
90 }
91
92 if (basename)
93- *basename = g_memdup (key + i + 1, key_len - i);
94+ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
95
96 return TRUE;
97 }
98--
99GitLab
100
101
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch
new file mode 100644
index 0000000000..8efb7c720f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-09.patch
@@ -0,0 +1,100 @@
1From 65ec7f4d6e8832c481f6e00e2eb007b9a60024ce Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 14:00:53 +0000
4Subject: [PATCH 09/11] =?UTF-8?q?gsocket:=20Use=20gsize=20to=20track=20nat?=
5 =?UTF-8?q?ive=20sockaddr=E2=80=99s=20size?=
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Don’t use an `int`, that’s potentially too small. In practical terms,
11this is not a problem, since no socket address is going to be that big.
12
13By making these changes we can use `g_memdup2()` without warnings,
14though. Fewer warnings is good.
15
16Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
17Helps: #2319
18
19Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
20CVE: CVE-2021-27219
21Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
22Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
23
24---
25 gio/gsocket.c | 16 ++++++++++------
26 1 file changed, 10 insertions(+), 6 deletions(-)
27
28--- a/gio/gsocket.c
29+++ b/gio/gsocket.c
30@@ -75,6 +75,7 @@
31 #include "gcredentialsprivate.h"
32 #include "glibintl.h"
33 #include "gioprivate.h"
34+#include "gstrfuncsprivate.h"
35
36 #ifdef G_OS_WIN32
37 /* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */
38@@ -174,7 +175,7 @@ static gboolean g_socket_datagram_ba
39 GError **error);
40
41 static GSocketAddress *
42-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len);
43+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len);
44
45 static gssize
46 g_socket_receive_message_with_timeout (GSocket *socket,
47@@ -260,7 +261,7 @@ struct _GSocketPrivate
48 struct {
49 GSocketAddress *addr;
50 struct sockaddr *native;
51- gint native_len;
52+ gsize native_len;
53 guint64 last_used;
54 } recv_addr_cache[RECV_ADDR_CACHE_SIZE];
55 };
56@@ -5259,14 +5260,14 @@ g_socket_send_messages_with_timeout (GSo
57 }
58
59 static GSocketAddress *
60-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len)
61+cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len)
62 {
63 GSocketAddress *saddr;
64 gint i;
65 guint64 oldest_time = G_MAXUINT64;
66 gint oldest_index = 0;
67
68- if (native_len <= 0)
69+ if (native_len == 0)
70 return NULL;
71
72 saddr = NULL;
73@@ -5274,7 +5275,7 @@ cache_recv_address (GSocket *socket, str
74 {
75 GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr;
76 gpointer tmp_native = socket->priv->recv_addr_cache[i].native;
77- gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
78+ gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len;
79
80 if (!tmp)
81 continue;
82@@ -5304,7 +5305,7 @@ cache_recv_address (GSocket *socket, str
83 g_free (socket->priv->recv_addr_cache[oldest_index].native);
84 }
85
86- socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len);
87+ socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len);
88 socket->priv->recv_addr_cache[oldest_index].native_len = native_len;
89 socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr);
90 socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time ();
91@@ -5452,6 +5453,9 @@ g_socket_receive_message_with_timeout (G
92 /* do it */
93 while (1)
94 {
95+ /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */
96+ G_STATIC_ASSERT (sizeof addr <= G_MAXINT);
97+
98 addrlen = sizeof addr;
99 if (address)
100 result = WSARecvFrom (socket->priv->fd,
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch
new file mode 100644
index 0000000000..63fda0b600
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-10.patch
@@ -0,0 +1,59 @@
1From 777b95a88f006d39d9fe6d3321db17e7b0d4b9a4 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 14:07:39 +0000
4Subject: [PATCH 10/11] gtlspassword: Forbid very long TLS passwords
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9The public API `g_tls_password_set_value_full()` (and the vfunc it
10invokes) can only accept a `gssize` length. Ensure that nul-terminated
11strings passed to `g_tls_password_set_value()` can’t exceed that length.
12Use `g_memdup2()` to avoid an overflow if they’re longer than
13`G_MAXUINT` similarly.
14
15Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
16Helps: #2319
17
18Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
19CVE: CVE-2021-27219
20Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
21Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
22
23---
24 gio/gtlspassword.c | 10 ++++++++--
25 1 file changed, 8 insertions(+), 2 deletions(-)
26
27diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
28index 1e437a7b6..dbcec41a8 100644
29--- a/gio/gtlspassword.c
30+++ b/gio/gtlspassword.c
31@@ -23,6 +23,7 @@
32 #include "glibintl.h"
33
34 #include "gioenumtypes.h"
35+#include "gstrfuncsprivate.h"
36 #include "gtlspassword.h"
37
38 #include <string.h>
39@@ -287,9 +288,14 @@ g_tls_password_set_value (GTlsPassword *password,
40 g_return_if_fail (G_IS_TLS_PASSWORD (password));
41
42 if (length < 0)
43- length = strlen ((gchar *)value);
44+ {
45+ /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
46+ gsize length_unsigned = strlen ((gchar *) value);
47+ g_return_if_fail (length_unsigned > G_MAXSSIZE);
48+ length = (gssize) length_unsigned;
49+ }
50
51- g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free);
52+ g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free);
53 }
54
55 /**
56--
57GitLab
58
59
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch
new file mode 100644
index 0000000000..a620a49269
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-11.patch
@@ -0,0 +1,63 @@
1From ecdf91400e9a538695a0895b95ad7e8abcdf1749 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 4 Feb 2021 14:09:40 +0000
4Subject: [PATCH 11/11] giochannel: Forbid very long line terminator strings
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9The public API `GIOChannel.line_term_len` is only a `guint`. Ensure that
10nul-terminated strings passed to `g_io_channel_set_line_term()` can’t
11exceed that length. Use `g_memdup2()` to avoid a warning (`g_memdup()`
12is due to be deprecated), but not to avoid a bug, since it’s also
13limited to `G_MAXUINT`.
14
15Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
16Helps: #2319
17
18Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
19CVE: CVE-2021-27219
20Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
21Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
22
23---
24 glib/giochannel.c | 17 +++++++++++++----
25 1 file changed, 13 insertions(+), 4 deletions(-)
26
27diff --git a/glib/giochannel.c b/glib/giochannel.c
28index c6a89d6e0..4dec20f77 100644
29--- a/glib/giochannel.c
30+++ b/glib/giochannel.c
31@@ -887,16 +887,25 @@ g_io_channel_set_line_term (GIOChannel *channel,
32 const gchar *line_term,
33 gint length)
34 {
35+ guint length_unsigned;
36+
37 g_return_if_fail (channel != NULL);
38 g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */
39
40 if (line_term == NULL)
41- length = 0;
42- else if (length < 0)
43- length = strlen (line_term);
44+ length_unsigned = 0;
45+ else if (length >= 0)
46+ length_unsigned = (guint) length;
47+ else
48+ {
49+ /* FIXME: We’re constrained by line_term_len being a guint here */
50+ gsize length_size = strlen (line_term);
51+ g_return_if_fail (length_size > G_MAXUINT);
52+ length_unsigned = (guint) length_size;
53+ }
54
55 g_free (channel->line_term);
56- channel->line_term = line_term ? g_memdup (line_term, length) : NULL;
57+ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
58 channel->line_term_len = length;
59 }
60
61--
62GitLab
63
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch
new file mode 100644
index 0000000000..3047062f54
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-1.patch
@@ -0,0 +1,36 @@
1From f8273b9aded135fe07094faebd527e43851aaf6e Mon Sep 17 00:00:00 2001
2From: "Jan Alexander Steffens (heftig)" <jan.steffens@gmail.com>
3Date: Sun, 7 Feb 2021 23:32:40 +0100
4Subject: [PATCH 1/5] giochannel: Fix length_size bounds check
5
6The inverted condition is an obvious error introduced by ecdf91400e9a.
7
8Fixes https://gitlab.gnome.org/GNOME/glib/-/issues/2323
9
10(cherry picked from commit a149bf2f9030168051942124536e303af8ba6176)
11
12Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
13CVE: CVE-2021-27219
14Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
15
16---
17 glib/giochannel.c | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/glib/giochannel.c b/glib/giochannel.c
21index 4dec20f77..c3f3102ff 100644
22--- a/glib/giochannel.c
23+++ b/glib/giochannel.c
24@@ -896,7 +896,7 @@ g_io_channel_set_line_term (GIOChannel *channel,
25 {
26 /* FIXME: We’re constrained by line_term_len being a guint here */
27 gsize length_size = strlen (line_term);
28- g_return_if_fail (length_size > G_MAXUINT);
29+ g_return_if_fail (length_size <= G_MAXUINT);
30 length_unsigned = (guint) length_size;
31 }
32
33--
34GitLab
35
36
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch
new file mode 100644
index 0000000000..2ba26075df
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-2.patch
@@ -0,0 +1,38 @@
1From e069c50467712e6d607822afd6b6c15c2c343dff Mon Sep 17 00:00:00 2001
2From: Simon McVittie <smcv@collabora.com>
3Date: Mon, 8 Feb 2021 10:34:50 +0000
4Subject: [PATCH 2/5] giochannel: Don't store negative line_term_len in
5 GIOChannel struct
6
7Adding test coverage indicated that this was another bug in 0cc11f74.
8
9Fixes: 0cc11f74 "giochannel: Forbid very long line terminator strings"
10Resolves: https://gitlab.gnome.org/GNOME/glib/-/issues/2323
11Signed-off-by: Simon McVittie <smcv@collabora.com>
12(cherry picked from commit 5dc8b0014c03e7491d93b90275ab442e888a9628)
13
14Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
15CVE: CVE-2021-27219
16Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
17
18---
19 glib/giochannel.c | 2 +-
20 1 file changed, 1 insertion(+), 1 deletion(-)
21
22diff --git a/glib/giochannel.c b/glib/giochannel.c
23index c3f3102ff..19bb06ba6 100644
24--- a/glib/giochannel.c
25+++ b/glib/giochannel.c
26@@ -902,7 +902,7 @@ g_io_channel_set_line_term (GIOChannel *channel,
27
28 g_free (channel->line_term);
29 channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL;
30- channel->line_term_len = length;
31+ channel->line_term_len = length_unsigned;
32 }
33
34 /**
35--
36GitLab
37
38
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch
new file mode 100644
index 0000000000..2c388b4bbb
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-4.patch
@@ -0,0 +1,38 @@
1From 4506d1859a863087598c8d122740bae25b65b099 Mon Sep 17 00:00:00 2001
2From: Simon McVittie <smcv@collabora.com>
3Date: Mon, 8 Feb 2021 10:04:48 +0000
4Subject: [PATCH 4/5] gtlspassword: Fix inverted assertion
5
6The intention here was to assert that the length of the password fits
7in a gssize. Passwords more than half the size of virtual memory are
8probably excessive.
9
10Fixes: a8b204ff "gtlspassword: Forbid very long TLS passwords"
11Signed-off-by: Simon McVittie <smcv@collabora.com>
12(cherry picked from commit 61bb52ec42de1082bfb06ce1c737fc295bfe60b8)
13
14Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
15CVE: CVE-2021-27219
16Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
17
18---
19 gio/gtlspassword.c | 2 +-
20 1 file changed, 1 insertion(+), 1 deletion(-)
21
22diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c
23index dbcec41a8..bd86a6dfe 100644
24--- a/gio/gtlspassword.c
25+++ b/gio/gtlspassword.c
26@@ -291,7 +291,7 @@ g_tls_password_set_value (GTlsPassword *password,
27 {
28 /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */
29 gsize length_unsigned = strlen ((gchar *) value);
30- g_return_if_fail (length_unsigned > G_MAXSSIZE);
31+ g_return_if_fail (length_unsigned <= G_MAXSSIZE);
32 length = (gssize) length_unsigned;
33 }
34
35--
36GitLab
37
38
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch
new file mode 100644
index 0000000000..356e986fe0
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg1-5.patch
@@ -0,0 +1,100 @@
1From 3d1550354c3c6a8491c39881752d51cb7515f2c2 Mon Sep 17 00:00:00 2001
2From: Simon McVittie <smcv@collabora.com>
3Date: Mon, 8 Feb 2021 10:22:39 +0000
4Subject: [PATCH 5/5] tls-interaction: Add test coverage for various ways to
5 set the password
6
7Signed-off-by: Simon McVittie <smcv@collabora.com>
8(cherry picked from commit df4501316ca3903072400504a5ea76498db19538)
9
10Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
11CVE: CVE-2021-27219
12Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
13
14---
15 gio/tests/tls-interaction.c | 55 +++++++++++++++++++++++++++++++++++++
16 1 file changed, 55 insertions(+)
17
18diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c
19index 4f0737d7e..5661e8e0d 100644
20--- a/gio/tests/tls-interaction.c
21+++ b/gio/tests/tls-interaction.c
22@@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction,
23 }
24
25
26+/* Return a copy of @str that is allocated in a silly way, to exercise
27+ * custom free-functions. The returned pointer points to a copy of @str
28+ * in a buffer of the form "BEFORE \0 str \0 AFTER". */
29+static guchar *
30+special_dup (const char *str)
31+{
32+ GString *buf = g_string_new ("BEFORE");
33+ guchar *ret;
34+
35+ g_string_append_c (buf, '\0');
36+ g_string_append (buf, str);
37+ g_string_append_c (buf, '\0');
38+ g_string_append (buf, "AFTER");
39+ ret = (guchar *) g_string_free (buf, FALSE);
40+ return ret + strlen ("BEFORE") + 1;
41+}
42+
43+
44+/* Free a copy of @str that was made with special_dup(), after asserting
45+ * that it has not been corrupted. */
46+static void
47+special_free (gpointer p)
48+{
49+ gchar *s = p;
50+ gchar *buf = s - strlen ("BEFORE") - 1;
51+
52+ g_assert_cmpstr (buf, ==, "BEFORE");
53+ g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER");
54+ g_free (buf);
55+}
56+
57+
58 static GTlsInteractionResult
59 test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
60 GTlsPassword *password,
61@@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
62 GError **error)
63 {
64 TestInteraction *self;
65+ const guchar *value;
66+ gsize len;
67
68 g_assert (TEST_IS_INTERACTION (interaction));
69 self = TEST_INTERACTION (interaction);
70@@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction,
71 g_assert (error != NULL);
72 g_assert (*error == NULL);
73
74+ /* Exercise different ways to set the value */
75+ g_tls_password_set_value (password, (const guchar *) "foo", 4);
76+ len = 0;
77+ value = g_tls_password_get_value (password, &len);
78+ g_assert_cmpmem (value, len, "foo", 4);
79+
80+ g_tls_password_set_value (password, (const guchar *) "bar", -1);
81+ len = 0;
82+ value = g_tls_password_get_value (password, &len);
83+ g_assert_cmpmem (value, len, "bar", 3);
84+
85+ g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free);
86+ len = 0;
87+ value = g_tls_password_get_value (password, &len);
88+ g_assert_cmpmem (value, len, "baa", 4);
89+
90+ g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free);
91+ len = 0;
92+ value = g_tls_password_get_value (password, &len);
93+ g_assert_cmpmem (value, len, "baz", 3);
94+
95 /* Don't do this in real life. Include a null terminator for testing */
96 g_tls_password_set_value (password, (const guchar *)"the password", 13);
97 return G_TLS_INTERACTION_HANDLED;
98--
99GitLab
100
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch
new file mode 100644
index 0000000000..dd43689aae
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-1.patch
@@ -0,0 +1,49 @@
1From cb9ee701ef46c1819eed4e2a4dc181682bdfc176 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 10 Feb 2021 21:16:39 +0000
4Subject: [PATCH 1/3] gkeyfilesettingsbackend: Fix basename handling when group
5 is unset
6
7Fix an effective regression in commit
87781a9cbd2fd0aa84bee0f4eee88470640ff6706, which happens when
9`convert_path()` is called with a `key` which contains no slashes. In
10that case, the `key` is entirely the `basename`.
11
12Prior to commit 7781a9cb, the code worked through a fluke of `i == -1`
13cancelling out with the various additions in the `g_memdup()` call, and
14effectively resulting in `g_strdup (key)`.
15
16Spotted by Guido Berhoerster.
17
18Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
19
20Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
21CVE: CVE-2021-27219
22Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
23
24---
25 gio/gkeyfilesettingsbackend.c | 7 ++++++-
26 1 file changed, 6 insertions(+), 1 deletion(-)
27
28diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
29index 25b057672..861c3a661 100644
30--- a/gio/gkeyfilesettingsbackend.c
31+++ b/gio/gkeyfilesettingsbackend.c
32@@ -185,7 +185,12 @@ convert_path (GKeyfileSettingsBackend *kfsb,
33 }
34
35 if (basename)
36- *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
37+ {
38+ if (last_slash != NULL)
39+ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key));
40+ else
41+ *basename = g_strdup (key);
42+ }
43
44 return TRUE;
45 }
46--
47GitLab
48
49
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch
new file mode 100644
index 0000000000..04503641c3
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-2.patch
@@ -0,0 +1,43 @@
1From 31e0d403ba635dbbacbfbff74295e5db02558d76 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 10 Feb 2021 21:19:30 +0000
4Subject: [PATCH 2/3] gkeyfilesettingsbackend: Disallow empty key or group
5 names
6
7These should never have been allowed; they will result in precondition
8failures from the `GKeyFile` later on in the code.
9
10A test will be added for this shortly.
11
12Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
13
14Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
15CVE: CVE-2021-27219
16Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
17
18---
19 gio/gkeyfilesettingsbackend.c | 7 +++++++
20 1 file changed, 7 insertions(+)
21
22diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c
23index 861c3a661..de216e615 100644
24--- a/gio/gkeyfilesettingsbackend.c
25+++ b/gio/gkeyfilesettingsbackend.c
26@@ -158,6 +158,13 @@ convert_path (GKeyfileSettingsBackend *kfsb,
27
28 last_slash = strrchr (key, '/');
29
30+ /* Disallow empty group names or key names */
31+ if (key_len == 0 ||
32+ (last_slash != NULL &&
33+ (*(last_slash + 1) == '\0' ||
34+ last_slash == key)))
35+ return FALSE;
36+
37 if (kfsb->root_group)
38 {
39 /* if a root_group was specified, make sure the user hasn't given
40--
41GitLab
42
43
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch
new file mode 100644
index 0000000000..65f59287a8
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219-reg2-3.patch
@@ -0,0 +1,232 @@
1Backport of:
2
3From 221c26685354dea2b2732df94404e8e5e77a1591 Mon Sep 17 00:00:00 2001
4From: Philip Withnall <pwithnall@endlessos.org>
5Date: Wed, 10 Feb 2021 21:21:36 +0000
6Subject: [PATCH 3/3] tests: Add tests for key name handling in the keyfile
7 backend
8
9This tests the two recent commits.
10
11Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
12
13Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
14CVE: CVE-2021-27219
15Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
16
17---
18 gio/tests/gsettings.c | 170 +++++++++++++++++++++++++++++++++++++++++-
19 1 file changed, 169 insertions(+), 1 deletion(-)
20
21--- a/gio/tests/gsettings.c
22+++ b/gio/tests/gsettings.c
23@@ -1,3 +1,4 @@
24+#include <errno.h>
25 #include <stdlib.h>
26 #include <locale.h>
27 #include <libintl.h>
28@@ -1740,6 +1741,14 @@ key_changed_cb (GSettings *settings, con
29 (*b) = TRUE;
30 }
31
32+typedef struct
33+{
34+ const gchar *path;
35+ const gchar *root_group;
36+ const gchar *keyfile_group;
37+ const gchar *root_path;
38+} KeyfileTestData;
39+
40 /*
41 * Test that using a keyfile works
42 */
43@@ -1834,7 +1843,11 @@ test_keyfile (Fixture *fixture,
44 g_free (str);
45
46 g_settings_set (settings, "farewell", "s", "cheerio");
47-
48+
49+ /* Check that empty keys/groups are not allowed. */
50+ g_assert_false (g_settings_is_writable (settings, ""));
51+ g_assert_false (g_settings_is_writable (settings, "/"));
52+
53 /* When executing as root, changing the mode of the keyfile will have
54 * no effect on the writability of the settings.
55 */
56@@ -1866,6 +1879,149 @@ test_keyfile (Fixture *fixture,
57 g_free (keyfile_path);
58 }
59
60+/*
61+ * Test that using a keyfile works with a schema with no path set.
62+ */
63+static void
64+test_keyfile_no_path (Fixture *fixture,
65+ gconstpointer user_data)
66+{
67+ const KeyfileTestData *test_data = user_data;
68+ GSettingsBackend *kf_backend;
69+ GSettings *settings;
70+ GKeyFile *keyfile;
71+ gboolean writable;
72+ gchar *key = NULL;
73+ GError *error = NULL;
74+ gchar *keyfile_path = NULL, *store_path = NULL;
75+
76+ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
77+ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
78+ kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group);
79+ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path);
80+ g_object_unref (kf_backend);
81+
82+ g_settings_reset (settings, "test-boolean");
83+ g_assert_true (g_settings_get_boolean (settings, "test-boolean"));
84+
85+ writable = g_settings_is_writable (settings, "test-boolean");
86+ g_assert_true (writable);
87+ g_settings_set (settings, "test-boolean", "b", FALSE);
88+
89+ g_assert_false (g_settings_get_boolean (settings, "test-boolean"));
90+
91+ g_settings_delay (settings);
92+ g_settings_set (settings, "test-boolean", "b", TRUE);
93+ g_settings_apply (settings);
94+
95+ keyfile = g_key_file_new ();
96+ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
97+
98+ g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL));
99+
100+ g_key_file_free (keyfile);
101+
102+ g_settings_reset (settings, "test-boolean");
103+ g_settings_apply (settings);
104+ keyfile = g_key_file_new ();
105+ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL));
106+
107+ g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error));
108+ g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND);
109+ g_clear_error (&error);
110+
111+ /* Check that empty keys/groups are not allowed. */
112+ g_assert_false (g_settings_is_writable (settings, ""));
113+ g_assert_false (g_settings_is_writable (settings, "/"));
114+
115+ /* Keys which ghost the root group name are not allowed. This can only be
116+ * tested when the path is `/` as otherwise it acts as a prefix and prevents
117+ * any ghosting. */
118+ if (g_str_equal (test_data->path, "/"))
119+ {
120+ key = g_strdup_printf ("%s/%s", test_data->root_group, "");
121+ g_assert_false (g_settings_is_writable (settings, key));
122+ g_free (key);
123+
124+ key = g_strdup_printf ("%s/%s", test_data->root_group, "/");
125+ g_assert_false (g_settings_is_writable (settings, key));
126+ g_free (key);
127+
128+ key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean");
129+ g_assert_false (g_settings_is_writable (settings, key));
130+ g_free (key);
131+ }
132+
133+ g_key_file_free (keyfile);
134+ g_object_unref (settings);
135+
136+ /* Clean up the temporary directory. */
137+ g_assert_cmpint (g_chmod (keyfile_path, 0777) == 0 ? 0 : errno, ==, 0);
138+ g_assert_cmpint (g_remove (store_path) == 0 ? 0 : errno, ==, 0);
139+ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
140+ g_free (store_path);
141+ g_free (keyfile_path);
142+}
143+
144+/*
145+ * Test that a keyfile rejects writes to keys outside its root path.
146+ */
147+static void
148+test_keyfile_outside_root_path (Fixture *fixture,
149+ gconstpointer user_data)
150+{
151+ GSettingsBackend *kf_backend;
152+ GSettings *settings;
153+ gchar *keyfile_path = NULL, *store_path = NULL;
154+
155+ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
156+ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
157+ kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root");
158+ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/");
159+ g_object_unref (kf_backend);
160+
161+ g_assert_false (g_settings_is_writable (settings, "test-boolean"));
162+
163+ g_object_unref (settings);
164+
165+ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
166+ * don’t error on failure. */
167+ g_remove (store_path);
168+ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
169+ g_free (store_path);
170+ g_free (keyfile_path);
171+}
172+
173+/*
174+ * Test that a keyfile rejects writes to keys in the root if no root group is set.
175+ */
176+static void
177+test_keyfile_no_root_group (Fixture *fixture,
178+ gconstpointer user_data)
179+{
180+ GSettingsBackend *kf_backend;
181+ GSettings *settings;
182+ gchar *keyfile_path = NULL, *store_path = NULL;
183+
184+ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL);
185+ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL);
186+ kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL);
187+ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/");
188+ g_object_unref (kf_backend);
189+
190+ g_assert_false (g_settings_is_writable (settings, "test-boolean"));
191+ g_assert_true (g_settings_is_writable (settings, "child/test-boolean"));
192+
193+ g_object_unref (settings);
194+
195+ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so
196+ * don’t error on failure. */
197+ g_remove (store_path);
198+ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0);
199+ g_free (store_path);
200+ g_free (keyfile_path);
201+}
202+
203 /* Test that getting child schemas works
204 */
205 static void
206@@ -2844,6 +3000,14 @@ main (int argc, char *argv[])
207 gchar *override_text;
208 gchar *enums;
209 gint result;
210+ const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" };
211+ const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" };
212+ const KeyfileTestData keyfile_test_data_long_path = {
213+ "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/",
214+ "root",
215+ "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch",
216+ "/"
217+ };
218
219 /* Meson build sets this */
220 #ifdef TEST_LOCALE_PATH
221@@ -2967,6 +3131,11 @@ main (int argc, char *argv[])
222 }
223
224 g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown);
225+ g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown);
226+ g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown);
227+ g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown);
228+ g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown);
229+ g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown);
230 g_test_add_func ("/gsettings/child-schema", test_child_schema);
231 g_test_add_func ("/gsettings/strinfo", test_strinfo);
232 g_test_add_func ("/gsettings/enums", test_enums);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch
new file mode 100644
index 0000000000..c89ca20726
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-1.patch
@@ -0,0 +1,27 @@
1From 78420a75aeb70569a8cd79fa0fea7b786b6f785f Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 24 Feb 2021 17:33:38 +0000
4Subject: [PATCH 1/5] glocalfileoutputstream: Fix a typo in a comment
5
6Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
7
8Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
9CVE: CVE-2021-28153
10Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
11Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
12
13---
14 gio/glocalfileoutputstream.c | 2 +-
15 1 file changed, 1 insertion(+), 1 deletion(-)
16
17--- a/gio/glocalfileoutputstream.c
18+++ b/gio/glocalfileoutputstream.c
19@@ -851,7 +851,7 @@ handle_overwrite_open (const char *fi
20 mode = mode_from_flags_or_info (flags, reference_info);
21
22 /* We only need read access to the original file if we are creating a backup.
23- * We also add O_CREATE to avoid a race if the file was just removed */
24+ * We also add O_CREAT to avoid a race if the file was just removed */
25 if (create_backup || readable)
26 open_flags = O_RDWR | O_CREAT | O_BINARY;
27 else
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch
new file mode 100644
index 0000000000..8a35bab4de
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-2.patch
@@ -0,0 +1,42 @@
1From 32d3d02a50e7dcec5f4cf7908e7ac88d575d8fc5 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 24 Feb 2021 17:34:32 +0000
4Subject: [PATCH 2/5] tests: Stop using g_test_bug_base() in file tests
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Since a following commit is going to add a new test which references
10Gitlab, so it’s best to move the URI bases inside the test cases.
11
12Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
13
14Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
15CVE: CVE-2021-28153
16Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
17Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
18
19---
20 gio/tests/file.c | 4 +---
21 1 file changed, 1 insertion(+), 3 deletions(-)
22
23--- a/gio/tests/file.c
24+++ b/gio/tests/file.c
25@@ -685,7 +685,7 @@ test_replace_cancel (void)
26 guint count;
27 GError *error = NULL;
28
29- g_test_bug ("629301");
30+ g_test_bug ("https://bugzilla.gnome.org/629301");
31
32 path = g_dir_make_tmp ("g_file_replace_cancel_XXXXXX", &error);
33 g_assert_no_error (error);
34@@ -1784,8 +1784,6 @@ main (int argc, char *argv[])
35 {
36 g_test_init (&argc, &argv, NULL);
37
38- g_test_bug_base ("http://bugzilla.gnome.org/");
39-
40 g_test_add_func ("/file/basic", test_basic);
41 g_test_add_func ("/file/build-filename", test_build_filename);
42 g_test_add_func ("/file/parent", test_parent);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch
new file mode 100644
index 0000000000..a82febd26e
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-3.patch
@@ -0,0 +1,57 @@
1Backport of:
2
3From ce0eb088a68171eed3ac217cb92a72e36eb57d1b Mon Sep 17 00:00:00 2001
4From: Philip Withnall <pwithnall@endlessos.org>
5Date: Wed, 10 Mar 2021 16:05:55 +0000
6Subject: [PATCH 3/5] glocalfileoutputstream: Factor out a flag check
7
8This clarifies the code a little. It introduces no functional changes.
9
10Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
11
12Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
13CVE: CVE-2021-28153
14Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
15Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
16
17---
18 gio/glocalfileoutputstream.c | 7 ++++---
19 1 file changed, 4 insertions(+), 3 deletions(-)
20
21--- a/gio/glocalfileoutputstream.c
22+++ b/gio/glocalfileoutputstream.c
23@@ -847,6 +847,7 @@ handle_overwrite_open (const char *fi
24 int res;
25 int mode;
26 int errsv;
27+ gboolean replace_destination_set = (flags & G_FILE_CREATE_REPLACE_DESTINATION);
28
29 mode = mode_from_flags_or_info (flags, reference_info);
30
31@@ -954,7 +955,7 @@ handle_overwrite_open (const char *fi
32 * to a backup file and rewrite the contents of the file.
33 */
34
35- if ((flags & G_FILE_CREATE_REPLACE_DESTINATION) ||
36+ if (replace_destination_set ||
37 (!(original_stat.st_nlink > 1) && !is_symlink))
38 {
39 char *dirname, *tmp_filename;
40@@ -973,7 +974,7 @@ handle_overwrite_open (const char *fi
41
42 /* try to keep permissions (unless replacing) */
43
44- if ( ! (flags & G_FILE_CREATE_REPLACE_DESTINATION) &&
45+ if (!replace_destination_set &&
46 (
47 #ifdef HAVE_FCHOWN
48 fchown (tmpfd, original_stat.st_uid, original_stat.st_gid) == -1 ||
49@@ -1112,7 +1113,7 @@ handle_overwrite_open (const char *fi
50 }
51 }
52
53- if (flags & G_FILE_CREATE_REPLACE_DESTINATION)
54+ if (replace_destination_set)
55 {
56 g_close (fd, NULL);
57
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch
new file mode 100644
index 0000000000..5b106e8474
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-4.patch
@@ -0,0 +1,265 @@
1Backport of:
2
3From 317b3b587058a05dca95d56dac26568c5b098d33 Mon Sep 17 00:00:00 2001
4From: Philip Withnall <pwithnall@endlessos.org>
5Date: Wed, 24 Feb 2021 17:36:07 +0000
6Subject: [PATCH 4/5] glocalfileoutputstream: Fix CREATE_REPLACE_DESTINATION
7 with symlinks
8MIME-Version: 1.0
9Content-Type: text/plain; charset=UTF-8
10Content-Transfer-Encoding: 8bit
11
12The `G_FILE_CREATE_REPLACE_DESTINATION` flag is equivalent to unlinking
13the destination file and re-creating it from scratch. That did
14previously work, but in the process the code would call `open(O_CREAT)`
15on the file. If the file was a dangling symlink, this would create the
16destination file (empty). That’s not an intended side-effect, and has
17security implications if the symlink is controlled by a lower-privileged
18process.
19
20Fix that by not opening the destination file if it’s a symlink, and
21adjusting the rest of the code to cope with
22 - the fact that `fd == -1` is not an error iff `is_symlink` is true,
23 - and that `original_stat` will contain the `lstat()` results for the
24 symlink now, rather than the `stat()` results for its target (again,
25 iff `is_symlink` is true).
26
27This means that the target of the dangling symlink is no longer created,
28which was the bug. The symlink itself continues to be replaced (as
29before) with the new file — this is the intended behaviour of
30`g_file_replace()`.
31
32The behaviour for non-symlink cases, or cases where the symlink was not
33dangling, should be unchanged.
34
35Includes a unit test.
36
37Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
38
39Fixes: #2325
40
41Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
42CVE: CVE-2021-28153
43Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
44Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
45
46---
47 gio/glocalfileoutputstream.c | 77 ++++++++++++++++++-------
48 gio/tests/file.c | 108 +++++++++++++++++++++++++++++++++++
49 2 files changed, 163 insertions(+), 22 deletions(-)
50
51--- a/gio/glocalfileoutputstream.c
52+++ b/gio/glocalfileoutputstream.c
53@@ -875,16 +875,22 @@ handle_overwrite_open (const char *fi
54 /* Could be a symlink, or it could be a regular ELOOP error,
55 * but then the next open will fail too. */
56 is_symlink = TRUE;
57- fd = g_open (filename, open_flags, mode);
58+ if (!replace_destination_set)
59+ fd = g_open (filename, open_flags, mode);
60 }
61-#else
62- fd = g_open (filename, open_flags, mode);
63- errsv = errno;
64+#else /* if !O_NOFOLLOW */
65 /* This is racy, but we do it as soon as possible to minimize the race */
66 is_symlink = g_file_test (filename, G_FILE_TEST_IS_SYMLINK);
67+
68+ if (!is_symlink || !replace_destination_set)
69+ {
70+ fd = g_open (filename, open_flags, mode);
71+ errsv = errno;
72+ }
73 #endif
74
75- if (fd == -1)
76+ if (fd == -1 &&
77+ (!is_symlink || !replace_destination_set))
78 {
79 char *display_name = g_filename_display_name (filename);
80 g_set_error (error, G_IO_ERROR,
81@@ -898,7 +904,14 @@ handle_overwrite_open (const char *fi
82 #ifdef G_OS_WIN32
83 res = GLIB_PRIVATE_CALL (g_win32_fstat) (fd, &original_stat);
84 #else
85- res = fstat (fd, &original_stat);
86+ if (!is_symlink)
87+ {
88+ res = fstat (fd, &original_stat);
89+ }
90+ else
91+ {
92+ res = lstat (filename, &original_stat);
93+ }
94 #endif
95 errsv = errno;
96
97@@ -917,16 +930,27 @@ handle_overwrite_open (const char *fi
98 if (!S_ISREG (original_stat.st_mode))
99 {
100 if (S_ISDIR (original_stat.st_mode))
101- g_set_error_literal (error,
102- G_IO_ERROR,
103- G_IO_ERROR_IS_DIRECTORY,
104- _("Target file is a directory"));
105- else
106- g_set_error_literal (error,
107+ {
108+ g_set_error_literal (error,
109+ G_IO_ERROR,
110+ G_IO_ERROR_IS_DIRECTORY,
111+ _("Target file is a directory"));
112+ goto err_out;
113+ }
114+ else if (!is_symlink ||
115+#ifdef S_ISLNK
116+ !S_ISLNK (original_stat.st_mode)
117+#else
118+ FALSE
119+#endif
120+ )
121+ {
122+ g_set_error_literal (error,
123 G_IO_ERROR,
124 G_IO_ERROR_NOT_REGULAR_FILE,
125 _("Target file is not a regular file"));
126- goto err_out;
127+ goto err_out;
128+ }
129 }
130
131 if (etag != NULL)
132@@ -1007,7 +1031,8 @@ handle_overwrite_open (const char *fi
133 }
134 }
135
136- g_close (fd, NULL);
137+ if (fd >= 0)
138+ g_close (fd, NULL);
139 *temp_filename = tmp_filename;
140 return tmpfd;
141 }
142--- a/gio/tests/file.c
143+++ b/gio/tests/file.c
144@@ -804,6 +804,113 @@ test_replace_cancel (void)
145 g_object_unref (tmpdir);
146 }
147
148+static void
149+test_replace_symlink (void)
150+{
151+#ifdef G_OS_UNIX
152+ gchar *tmpdir_path = NULL;
153+ GFile *tmpdir = NULL, *source_file = NULL, *target_file = NULL;
154+ GFileOutputStream *stream = NULL;
155+ const gchar *new_contents = "this is a test message which should be written to source and not target";
156+ gsize n_written;
157+ GFileEnumerator *enumerator = NULL;
158+ GFileInfo *info = NULL;
159+ gchar *contents = NULL;
160+ gsize length = 0;
161+ GError *local_error = NULL;
162+
163+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2325");
164+ g_test_summary ("Test that G_FILE_CREATE_REPLACE_DESTINATION doesn’t follow symlinks");
165+
166+ /* Create a fresh, empty working directory. */
167+ tmpdir_path = g_dir_make_tmp ("g_file_replace_symlink_XXXXXX", &local_error);
168+ g_assert_no_error (local_error);
169+ tmpdir = g_file_new_for_path (tmpdir_path);
170+
171+ g_test_message ("Using temporary directory %s", tmpdir_path);
172+ g_free (tmpdir_path);
173+
174+ /* Create symlink `source` which points to `target`. */
175+ source_file = g_file_get_child (tmpdir, "source");
176+ target_file = g_file_get_child (tmpdir, "target");
177+ g_file_make_symbolic_link (source_file, "target", NULL, &local_error);
178+ g_assert_no_error (local_error);
179+
180+ /* Ensure that `target` doesn’t exist */
181+ g_assert_false (g_file_query_exists (target_file, NULL));
182+
183+ /* Replace the `source` symlink with a regular file using
184+ * %G_FILE_CREATE_REPLACE_DESTINATION, which should replace it *without*
185+ * following the symlink */
186+ stream = g_file_replace (source_file, NULL, FALSE /* no backup */,
187+ G_FILE_CREATE_REPLACE_DESTINATION, NULL, &local_error);
188+ g_assert_no_error (local_error);
189+
190+ g_output_stream_write_all (G_OUTPUT_STREAM (stream), new_contents, strlen (new_contents),
191+ &n_written, NULL, &local_error);
192+ g_assert_no_error (local_error);
193+ g_assert_cmpint (n_written, ==, strlen (new_contents));
194+
195+ g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, &local_error);
196+ g_assert_no_error (local_error);
197+
198+ g_clear_object (&stream);
199+
200+ /* At this point, there should still only be one file: `source`. It should
201+ * now be a regular file. `target` should not exist. */
202+ enumerator = g_file_enumerate_children (tmpdir,
203+ G_FILE_ATTRIBUTE_STANDARD_NAME ","
204+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
205+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &local_error);
206+ g_assert_no_error (local_error);
207+
208+ info = g_file_enumerator_next_file (enumerator, NULL, &local_error);
209+ g_assert_no_error (local_error);
210+ g_assert_nonnull (info);
211+
212+ g_assert_cmpstr (g_file_info_get_name (info), ==, "source");
213+ g_assert_cmpint (g_file_info_get_file_type (info), ==, G_FILE_TYPE_REGULAR);
214+
215+ g_clear_object (&info);
216+
217+ info = g_file_enumerator_next_file (enumerator, NULL, &local_error);
218+ g_assert_no_error (local_error);
219+ g_assert_null (info);
220+
221+ g_file_enumerator_close (enumerator, NULL, &local_error);
222+ g_assert_no_error (local_error);
223+ g_clear_object (&enumerator);
224+
225+ /* Double-check that `target` doesn’t exist */
226+ g_assert_false (g_file_query_exists (target_file, NULL));
227+
228+ /* Check the content of `source`. */
229+ g_file_load_contents (source_file,
230+ NULL,
231+ &contents,
232+ &length,
233+ NULL,
234+ &local_error);
235+ g_assert_no_error (local_error);
236+ g_assert_cmpstr (contents, ==, new_contents);
237+ g_assert_cmpuint (length, ==, strlen (new_contents));
238+ g_free (contents);
239+
240+ /* Tidy up. */
241+ g_file_delete (source_file, NULL, &local_error);
242+ g_assert_no_error (local_error);
243+
244+ g_file_delete (tmpdir, NULL, &local_error);
245+ g_assert_no_error (local_error);
246+
247+ g_clear_object (&target_file);
248+ g_clear_object (&source_file);
249+ g_clear_object (&tmpdir);
250+#else /* if !G_OS_UNIX */
251+ g_test_skip ("Symlink replacement tests can only be run on Unix")
252+#endif
253+}
254+
255 static void
256 on_file_deleted (GObject *object,
257 GAsyncResult *result,
258@@ -1752,6 +1859,7 @@ main (int argc, char *argv[])
259 g_test_add_data_func ("/file/async-create-delete/4096", GINT_TO_POINTER (4096), test_create_delete);
260 g_test_add_func ("/file/replace-load", test_replace_load);
261 g_test_add_func ("/file/replace-cancel", test_replace_cancel);
262+ g_test_add_func ("/file/replace-symlink", test_replace_symlink);
263 g_test_add_func ("/file/async-delete", test_async_delete);
264 #ifdef G_OS_UNIX
265 g_test_add_func ("/file/copy-preserve-mode", test_copy_preserve_mode);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch
new file mode 100644
index 0000000000..2334147f7d
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-28153-5.patch
@@ -0,0 +1,55 @@
1From 6c6439261bc7a8a0627519848a7222b3e1bd4ffe Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 24 Feb 2021 17:42:24 +0000
4Subject: [PATCH 5/5] glocalfileoutputstream: Add a missing O_CLOEXEC flag to
5 replace()
6
7Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
8
9Upstream-Status: Backport [https://mirrors.ocf.berkeley.edu/ubuntu/pool/main/g/glib2.0/glib2.0_2.64.6-1~ubuntu20.04.3.debian.tar.xz]
10CVE: CVE-2021-28153
11Signed-off-by: Neetika Singh <Neetika.Singh@kpit.com>
12Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
13
14---
15 gio/glocalfileoutputstream.c | 15 ++++++++++++---
16 1 file changed, 12 insertions(+), 3 deletions(-)
17
18--- a/gio/glocalfileoutputstream.c
19+++ b/gio/glocalfileoutputstream.c
20@@ -58,6 +58,12 @@
21 #define O_BINARY 0
22 #endif
23
24+#ifndef O_CLOEXEC
25+#define O_CLOEXEC 0
26+#else
27+#define HAVE_O_CLOEXEC 1
28+#endif
29+
30 struct _GLocalFileOutputStreamPrivate {
31 char *tmp_filename;
32 char *original_filename;
33@@ -1223,7 +1229,7 @@ _g_local_file_output_stream_replace (con
34 sync_on_close = FALSE;
35
36 /* If the file doesn't exist, create it */
37- open_flags = O_CREAT | O_EXCL | O_BINARY;
38+ open_flags = O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC;
39 if (readable)
40 open_flags |= O_RDWR;
41 else
42@@ -1253,8 +1259,11 @@ _g_local_file_output_stream_replace (con
43 set_error_from_open_errno (filename, error);
44 return NULL;
45 }
46-
47-
48+#if !defined(HAVE_O_CLOEXEC) && defined(F_SETFD)
49+ else
50+ fcntl (fd, F_SETFD, FD_CLOEXEC);
51+#endif
52+
53 stream = g_object_new (G_TYPE_LOCAL_FILE_OUTPUT_STREAM, NULL);
54 stream->priv->fd = fd;
55 stream->priv->sync_on_close = sync_on_close;
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
new file mode 100644
index 0000000000..ce90586290
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
@@ -0,0 +1,290 @@
1From 5f4485c4ff57fdefb1661531788def7ca5a47328 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 04:19:44 +0000
4Subject: [PATCH] gvariant-serialiser: Check offset table entry size is minimal
5
6The entries in an offset table (which is used for variable sized arrays
7and tuples containing variable sized members) are sized so that they can
8address every byte in the overall variant.
9
10The specification requires that for a variant to be in normal form, its
11offset table entries must be the minimum width such that they can
12address every byte in the variant.
13
14That minimality requirement was not checked in
15`g_variant_is_normal_form()`, leading to two different byte arrays being
16interpreted as the normal form of a given variant tree. That kind of
17confusion could potentially be exploited, and is certainly a bug.
18
19Fix it by adding the necessary checks on offset table entry width, and
20unit tests.
21
22Spotted by William Manley.
23
24Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
25
26Fixes: #2794
27
28CVE: CVE-2023-29499
29Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/5f4485c4ff57fdefb1661531788def7ca5a47328]
30Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
31---
32 glib/gvariant-serialiser.c | 19 +++-
33 glib/tests/gvariant.c | 176 +++++++++++++++++++++++++++++++++++++
34 2 files changed, 194 insertions(+), 1 deletion(-)
35
36diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
37index 0bf7243..5aa2cbc 100644
38--- a/glib/gvariant-serialiser.c
39+++ b/glib/gvariant-serialiser.c
40@@ -694,6 +694,10 @@ gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
41 out.data_size = last_end;
42 out.array = value.data + last_end;
43 out.length = offsets_array_size / out.offset_size;
44+
45+ if (out.length > 0 && gvs_calculate_total_size (last_end, out.length) != value.size)
46+ return out; /* offset size not minimal */
47+
48 out.is_normal = TRUE;
49
50 return out;
51@@ -1201,6 +1205,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
52 gsize length;
53 gsize offset;
54 gsize i;
55+ gsize offset_table_size;
56
57 /* as per the comment in gvs_tuple_get_child() */
58 if G_UNLIKELY (value.data == NULL && value.size != 0)
59@@ -1305,7 +1310,19 @@ gvs_tuple_is_normal (GVariantSerialised value)
60 }
61 }
62
63- return offset_ptr == offset;
64+ /* @offset_ptr has been counting backwards from the end of the variant, to
65+ * find the beginning of the offset table. @offset has been counting forwards
66+ * from the beginning of the variant to find the end of the data. They should
67+ * have met in the middle. */
68+ if (offset_ptr != offset)
69+ return FALSE;
70+
71+ offset_table_size = value.size - offset_ptr;
72+ if (value.size > 0 &&
73+ gvs_calculate_total_size (offset, offset_table_size / offset_size) != value.size)
74+ return FALSE; /* offset size not minimal */
75+
76+ return TRUE;
77 }
78
79 /* Variants {{{2
80diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
81index d640c81..4ce0e4f 100644
82--- a/glib/tests/gvariant.c
83+++ b/glib/tests/gvariant.c
84@@ -5092,6 +5092,86 @@ test_normal_checking_array_offsets2 (void)
85 g_variant_unref (variant);
86 }
87
88+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
89+ * its offset table entries are too wide.
90+ *
91+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
92+static void
93+test_normal_checking_array_offsets_minimal_sized (void)
94+{
95+ GVariantBuilder builder;
96+ gsize i;
97+ GVariant *aay_constructed = NULL;
98+ const guint8 *data = NULL;
99+ guint8 *data_owned = NULL;
100+ GVariant *aay_deserialised = NULL;
101+ GVariant *aay_normalised = NULL;
102+
103+ /* Construct an array of type aay, consisting of 128 elements which are each
104+ * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
105+ * elements are variable sized (making the outer array variable sized, so it
106+ * must have an offset table), but they are also zero-sized when serialised.
107+ * So the serialised representation of @aay_constructed consists entirely of
108+ * its offset table, which is entirely zeroes.
109+ *
110+ * The array is chosen to be 128 elements long because that means offset
111+ * table entries which are 1 byte long. If the elements in the array were
112+ * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
113+ * the offset table entries would end up being 2 bytes long. */
114+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
115+
116+ for (i = 0; i < 128; i++)
117+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
118+
119+ aay_constructed = g_variant_builder_end (&builder);
120+
121+ /* Verify that the constructed array is in normal form, and its serialised
122+ * form is `b'\0' * 128`. */
123+ g_assert_true (g_variant_is_normal_form (aay_constructed));
124+ g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
125+ g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
126+
127+ data = g_variant_get_data (aay_constructed);
128+ for (i = 0; i < g_variant_get_size (aay_constructed); i++)
129+ g_assert_cmpuint (data[i], ==, 0);
130+
131+ /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
132+ * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
133+ * entries, because each offset table entry has to be able to reference all of
134+ * the byte boundaries in the container. All the entries in the offset table
135+ * are zero, so all the elements of the array are zero-sized. */
136+ data = data_owned = g_malloc0 (256);
137+ aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
138+ data,
139+ 256,
140+ FALSE,
141+ g_free,
142+ g_steal_pointer (&data_owned));
143+
144+ g_assert_false (g_variant_is_normal_form (aay_deserialised));
145+ g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
146+ g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
147+
148+ data = g_variant_get_data (aay_deserialised);
149+ for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
150+ g_assert_cmpuint (data[i], ==, 0);
151+
152+ /* Get its normal form. That should change the serialised size. */
153+ aay_normalised = g_variant_get_normal_form (aay_deserialised);
154+
155+ g_assert_true (g_variant_is_normal_form (aay_normalised));
156+ g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
157+ g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
158+
159+ data = g_variant_get_data (aay_normalised);
160+ for (i = 0; i < g_variant_get_size (aay_normalised); i++)
161+ g_assert_cmpuint (data[i], ==, 0);
162+
163+ g_variant_unref (aay_normalised);
164+ g_variant_unref (aay_deserialised);
165+ g_variant_unref (aay_constructed);
166+}
167+
168 /* Test that a tuple with invalidly large values in its offset table is
169 * normalised successfully without looping infinitely. */
170 static void
171@@ -5286,6 +5366,98 @@ test_normal_checking_tuple_offsets4 (void)
172 g_variant_unref (variant);
173 }
174
175+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
176+ * its offset table entries are too wide.
177+ *
178+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
179+static void
180+test_normal_checking_tuple_offsets_minimal_sized (void)
181+{
182+ GString *type_string = NULL;
183+ GVariantBuilder builder;
184+ gsize i;
185+ GVariant *ray_constructed = NULL;
186+ const guint8 *data = NULL;
187+ guint8 *data_owned = NULL;
188+ GVariant *ray_deserialised = NULL;
189+ GVariant *ray_normalised = NULL;
190+
191+ /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
192+ * an empty array, i.e. `([] * 129)`. This is chosen because the inner
193+ * members are variable sized, so the outer tuple must have an offset table,
194+ * but they are also zero-sized when serialised. So the serialised
195+ * representation of @ray_constructed consists entirely of its offset table,
196+ * which is entirely zeroes.
197+ *
198+ * The tuple is chosen to be 129 members long because that means it has 128
199+ * offset table entries which are 1 byte long each. If the members in the
200+ * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
201+ * bytes long), the offset table entries would end up being 2 bytes long.
202+ *
203+ * 129 members are used unlike 128 array elements in
204+ * test_normal_checking_array_offsets_minimal_sized(), because the last member
205+ * in a tuple never needs an offset table entry. */
206+ type_string = g_string_new ("");
207+ g_string_append_c (type_string, '(');
208+ for (i = 0; i < 129; i++)
209+ g_string_append (type_string, "ay");
210+ g_string_append_c (type_string, ')');
211+
212+ g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
213+
214+ for (i = 0; i < 129; i++)
215+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
216+
217+ ray_constructed = g_variant_builder_end (&builder);
218+
219+ /* Verify that the constructed tuple is in normal form, and its serialised
220+ * form is `b'\0' * 128`. */
221+ g_assert_true (g_variant_is_normal_form (ray_constructed));
222+ g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
223+ g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
224+
225+ data = g_variant_get_data (ray_constructed);
226+ for (i = 0; i < g_variant_get_size (ray_constructed); i++)
227+ g_assert_cmpuint (data[i], ==, 0);
228+
229+ /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
230+ * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
231+ * entries, because each offset table entry has to be able to reference all of
232+ * the byte boundaries in the container. All the entries in the offset table
233+ * are zero, so all the members of the tuple are zero-sized. */
234+ data = data_owned = g_malloc0 (256);
235+ ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
236+ data,
237+ 256,
238+ FALSE,
239+ g_free,
240+ g_steal_pointer (&data_owned));
241+
242+ g_assert_false (g_variant_is_normal_form (ray_deserialised));
243+ g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
244+ g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
245+
246+ data = g_variant_get_data (ray_deserialised);
247+ for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
248+ g_assert_cmpuint (data[i], ==, 0);
249+
250+ /* Get its normal form. That should change the serialised size. */
251+ ray_normalised = g_variant_get_normal_form (ray_deserialised);
252+
253+ g_assert_true (g_variant_is_normal_form (ray_normalised));
254+ g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
255+ g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
256+
257+ data = g_variant_get_data (ray_normalised);
258+ for (i = 0; i < g_variant_get_size (ray_normalised); i++)
259+ g_assert_cmpuint (data[i], ==, 0);
260+
261+ g_variant_unref (ray_normalised);
262+ g_variant_unref (ray_deserialised);
263+ g_variant_unref (ray_constructed);
264+ g_string_free (type_string, TRUE);
265+}
266+
267 /* Test that an empty object path is normalised successfully to the base object
268 * path, ‘/’. */
269 static void
270@@ -5431,6 +5603,8 @@ main (int argc, char **argv)
271 test_normal_checking_array_offsets);
272 g_test_add_func ("/gvariant/normal-checking/array-offsets2",
273 test_normal_checking_array_offsets2);
274+ g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
275+ test_normal_checking_array_offsets_minimal_sized);
276 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
277 test_normal_checking_tuple_offsets);
278 g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
279@@ -5439,6 +5613,8 @@ main (int argc, char **argv)
280 test_normal_checking_tuple_offsets3);
281 g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
282 test_normal_checking_tuple_offsets4);
283+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
284+ test_normal_checking_tuple_offsets_minimal_sized);
285 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
286 test_normal_checking_empty_object_path);
287
288--
2892.24.4
290
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch
new file mode 100644
index 0000000000..b2187f2af9
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0001.patch
@@ -0,0 +1,89 @@
1From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:04:49 +0000
4Subject: [PATCH] gvariant-core: Consolidate construction of
5 `GVariantSerialised`
6
7So I only need to change it in one place.
8
9This introduces no functional changes.
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
15Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
16---
17 glib/gvariant.c | 8 +++++---
18 glib/tests/gvariant.c | 24 ++++++++++++++++++++++++
19 2 files changed, 29 insertions(+), 3 deletions(-)
20
21diff --git a/glib/gvariant.c b/glib/gvariant.c
22index 8ba701e..4dbd9e8 100644
23--- a/glib/gvariant.c
24+++ b/glib/gvariant.c
25@@ -5952,14 +5952,16 @@ g_variant_byteswap (GVariant *value)
26 g_variant_serialised_byteswap (serialised);
27
28 bytes = g_bytes_new_take (serialised.data, serialised.size);
29- new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE);
30+ new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
31 g_bytes_unref (bytes);
32 }
33 else
34 /* contains no multi-byte data */
35- new = value;
36+ new = g_variant_get_normal_form (value);
37
38- return g_variant_ref_sink (new);
39+ g_assert (g_variant_is_trusted (new));
40+
41+ return g_steal_pointer (&new);
42 }
43
44 /**
45diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
46index 4ce0e4f..3dda08e 100644
47--- a/glib/tests/gvariant.c
48+++ b/glib/tests/gvariant.c
49@@ -3834,6 +3834,29 @@ test_gv_byteswap (void)
50 g_free (string);
51 }
52
53+static void
54+test_gv_byteswap_non_normal_non_aligned (void)
55+{
56+ const guint8 data[] = { 0x02 };
57+ GVariant *v = NULL;
58+ GVariant *v_byteswapped = NULL;
59+
60+ g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
61+ "is in non-normal form and doesn’t need byteswapping returns "
62+ "the same variant in normal form.");
63+
64+ v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
65+ g_assert_false (g_variant_is_normal_form (v));
66+
67+ v_byteswapped = g_variant_byteswap (v);
68+ g_assert_true (g_variant_is_normal_form (v_byteswapped));
69+
70+ g_assert_cmpvariant (v, v_byteswapped);
71+
72+ g_variant_unref (v);
73+ g_variant_unref (v_byteswapped);
74+}
75+
76 static void
77 test_parser (void)
78 {
79@@ -5570,6 +5593,7 @@ main (int argc, char **argv)
80 g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
81 g_test_add_func ("/gvariant/hashing", test_hashing);
82 g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
83+ g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
84 g_test_add_func ("/gvariant/parser", test_parses);
85 g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
86 g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
87--
882.24.4
89
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
new file mode 100644
index 0000000000..9167ea624f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
@@ -0,0 +1,255 @@
1From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:39:34 +0000
4Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
5 framing offsets
6
7This introduces no functional changes.
8
9Helps: #2121
10
11CVE: CVE-2023-32665
12Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
13Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
14---
15 glib/gvariant.c | 81 +++++++++++++++++++++++++++++++++----------
16 glib/tests/gvariant.c | 57 ++++++++++++++++++++++++++----
17 2 files changed, 112 insertions(+), 26 deletions(-)
18
19diff --git a/glib/gvariant.c b/glib/gvariant.c
20index 4dbd9e8..a80c2c9 100644
21--- a/glib/gvariant.c
22+++ b/glib/gvariant.c
23@@ -5788,7 +5788,8 @@ g_variant_iter_loop (GVariantIter *iter,
24
25 /* Serialised data {{{1 */
26 static GVariant *
27-g_variant_deep_copy (GVariant *value)
28+g_variant_deep_copy (GVariant *value,
29+ gboolean byteswap)
30 {
31 switch (g_variant_classify (value))
32 {
33@@ -5806,7 +5807,7 @@ g_variant_deep_copy (GVariant *value)
34 for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
35 {
36 GVariant *child = g_variant_get_child_value (value, i);
37- g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
38+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap));
39 g_variant_unref (child);
40 }
41
42@@ -5820,28 +5821,63 @@ g_variant_deep_copy (GVariant *value)
43 return g_variant_new_byte (g_variant_get_byte (value));
44
45 case G_VARIANT_CLASS_INT16:
46- return g_variant_new_int16 (g_variant_get_int16 (value));
47+ if (byteswap)
48+ return g_variant_new_int16 (GUINT16_SWAP_LE_BE (g_variant_get_int16 (value)));
49+ else
50+ return g_variant_new_int16 (g_variant_get_int16 (value));
51
52 case G_VARIANT_CLASS_UINT16:
53- return g_variant_new_uint16 (g_variant_get_uint16 (value));
54+ if (byteswap)
55+ return g_variant_new_uint16 (GUINT16_SWAP_LE_BE (g_variant_get_uint16 (value)));
56+ else
57+ return g_variant_new_uint16 (g_variant_get_uint16 (value));
58
59 case G_VARIANT_CLASS_INT32:
60- return g_variant_new_int32 (g_variant_get_int32 (value));
61+ if (byteswap)
62+ return g_variant_new_int32 (GUINT32_SWAP_LE_BE (g_variant_get_int32 (value)));
63+ else
64+ return g_variant_new_int32 (g_variant_get_int32 (value));
65
66 case G_VARIANT_CLASS_UINT32:
67- return g_variant_new_uint32 (g_variant_get_uint32 (value));
68+ if (byteswap)
69+ return g_variant_new_uint32 (GUINT32_SWAP_LE_BE (g_variant_get_uint32 (value)));
70+ else
71+ return g_variant_new_uint32 (g_variant_get_uint32 (value));
72
73 case G_VARIANT_CLASS_INT64:
74- return g_variant_new_int64 (g_variant_get_int64 (value));
75+ if (byteswap)
76+ return g_variant_new_int64 (GUINT64_SWAP_LE_BE (g_variant_get_int64 (value)));
77+ else
78+ return g_variant_new_int64 (g_variant_get_int64 (value));
79
80 case G_VARIANT_CLASS_UINT64:
81- return g_variant_new_uint64 (g_variant_get_uint64 (value));
82+ if (byteswap)
83+ return g_variant_new_uint64 (GUINT64_SWAP_LE_BE (g_variant_get_uint64 (value)));
84+ else
85+ return g_variant_new_uint64 (g_variant_get_uint64 (value));
86
87 case G_VARIANT_CLASS_HANDLE:
88- return g_variant_new_handle (g_variant_get_handle (value));
89+ if (byteswap)
90+ return g_variant_new_handle (GUINT32_SWAP_LE_BE (g_variant_get_handle (value)));
91+ else
92+ return g_variant_new_handle (g_variant_get_handle (value));
93
94 case G_VARIANT_CLASS_DOUBLE:
95- return g_variant_new_double (g_variant_get_double (value));
96+ if (byteswap)
97+ {
98+ /* We have to convert the double to a uint64 here using a union,
99+ * because a cast will round it numerically. */
100+ union
101+ {
102+ guint64 u64;
103+ gdouble dbl;
104+ } u1, u2;
105+ u1.dbl = g_variant_get_double (value);
106+ u2.u64 = GUINT64_SWAP_LE_BE (u1.u64);
107+ return g_variant_new_double (u2.dbl);
108+ }
109+ else
110+ return g_variant_new_double (g_variant_get_double (value));
111
112 case G_VARIANT_CLASS_STRING:
113 return g_variant_new_string (g_variant_get_string (value, NULL));
114@@ -5896,7 +5932,7 @@ g_variant_get_normal_form (GVariant *value)
115 if (g_variant_is_normal_form (value))
116 return g_variant_ref (value);
117
118- trusted = g_variant_deep_copy (value);
119+ trusted = g_variant_deep_copy (value, FALSE);
120 g_assert (g_variant_is_trusted (trusted));
121
122 return g_variant_ref_sink (trusted);
123@@ -5916,6 +5952,11 @@ g_variant_get_normal_form (GVariant *value)
124 * contain multi-byte numeric data. That include strings, booleans,
125 * bytes and containers containing only these things (recursively).
126 *
127+ * While this function can safely handle untrusted, non-normal data, it is
128+ * recommended to check whether the input is in normal form beforehand, using
129+ * g_variant_is_normal_form(), and to reject non-normal inputs if your
130+ * application can be strict about what inputs it rejects.
131+ *
132 * The returned value is always in normal form and is marked as trusted.
133 *
134 * Returns: (transfer full): the byteswapped form of @value
135@@ -5933,21 +5974,20 @@ g_variant_byteswap (GVariant *value)
136
137 g_variant_type_info_query (type_info, &alignment, NULL);
138
139- if (alignment)
140- /* (potentially) contains multi-byte numeric data */
141+ if (alignment && g_variant_is_normal_form (value))
142 {
143+ /* (potentially) contains multi-byte numeric data, but is also already in
144+ * normal form so we can use a faster byteswapping codepath on the
145+ * serialised data */
146 GVariantSerialised serialised = { 0, };
147- GVariant *trusted;
148 GBytes *bytes;
149
150- trusted = g_variant_get_normal_form (value);
151- serialised.type_info = g_variant_get_type_info (trusted);
152- serialised.size = g_variant_get_size (trusted);
153+ serialised.type_info = g_variant_get_type_info (value);
154+ serialised.size = g_variant_get_size (value);
155 serialised.data = g_malloc (serialised.size);
156 serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
157 serialised.checked_offsets_up_to = G_MAXSIZE;
158- g_variant_store (trusted, serialised.data);
159- g_variant_unref (trusted);
160+ g_variant_store (value, serialised.data);
161
162 g_variant_serialised_byteswap (serialised);
163
164@@ -5955,6 +5995,9 @@ g_variant_byteswap (GVariant *value)
165 new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
166 g_bytes_unref (bytes);
167 }
168+ else if (alignment)
169+ /* (potentially) contains multi-byte numeric data */
170+ new = g_variant_ref_sink (g_variant_deep_copy (value, TRUE));
171 else
172 /* contains no multi-byte data */
173 new = g_variant_get_normal_form (value);
174diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
175index 3dda08e..679dd40 100644
176--- a/glib/tests/gvariant.c
177+++ b/glib/tests/gvariant.c
178@@ -2284,24 +2284,67 @@ serialise_tree (TreeInstance *tree,
179 static void
180 test_byteswap (void)
181 {
182- GVariantSerialised one = { 0, }, two = { 0, };
183+ GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
184 TreeInstance *tree;
185-
186+ GVariant *one_variant = NULL;
187+ GVariant *two_variant = NULL;
188+ GVariant *two_byteswapped = NULL;
189+ GVariant *three_variant = NULL;
190+ GVariant *three_byteswapped = NULL;
191+ guint8 *three_data_copy = NULL;
192+ gsize three_size_copy = 0;
193+
194+ /* Write a tree out twice, once normally and once byteswapped. */
195 tree = tree_instance_new (NULL, 3);
196 serialise_tree (tree, &one);
197
198+ one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
199+ one.data, one.size, FALSE, NULL, NULL);
200+
201 i_am_writing_byteswapped = TRUE;
202 serialise_tree (tree, &two);
203+ serialise_tree (tree, &three);
204 i_am_writing_byteswapped = FALSE;
205
206- g_variant_serialised_byteswap (two);
207-
208- g_assert_cmpmem (one.data, one.size, two.data, two.size);
209- g_assert_cmpuint (one.depth, ==, two.depth);
210-
211+ /* Swap the first byteswapped one back using the function we want to test. */
212+ two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
213+ two.data, two.size, FALSE, NULL, NULL);
214+ two_byteswapped = g_variant_byteswap (two_variant);
215+
216+ /* Make the second byteswapped one non-normal (hopefully), and then byteswap
217+ * it back using the function we want to test in its non-normal mode.
218+ * This might not work because it’s not necessarily possible to make an
219+ * arbitrary random variant non-normal. Adding a single zero byte to the end
220+ * often makes something non-normal but still readable. */
221+ three_size_copy = three.size + 1;
222+ three_data_copy = g_malloc (three_size_copy);
223+ memcpy (three_data_copy, three.data, three.size);
224+ three_data_copy[three.size] = '\0';
225+
226+ three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
227+ three_data_copy, three_size_copy, FALSE, NULL, NULL);
228+ three_byteswapped = g_variant_byteswap (three_variant);
229+
230+ /* Check they’re the same. We can always compare @one_variant and
231+ * @two_byteswapped. We can only compare @two_byteswapped and
232+ * @three_byteswapped if @two_variant and @three_variant are equal: in that
233+ * case, the corruption to @three_variant was enough to make it non-normal but
234+ * not enough to change its value. */
235+ g_assert_cmpvariant (one_variant, two_byteswapped);
236+
237+ if (g_variant_equal (two_variant, three_variant))
238+ g_assert_cmpvariant (two_byteswapped, three_byteswapped);
239+
240+ g_variant_unref (three_byteswapped);
241+ g_variant_unref (three_variant);
242+ g_variant_unref (two_byteswapped);
243+ g_variant_unref (two_variant);
244+ g_variant_unref (one_variant);
245 tree_instance_free (tree);
246 g_free (one.data);
247 g_free (two.data);
248+ g_free (three.data);
249+ g_free (three_data_copy);
250 }
251
252 static void
253--
2542.24.4
255
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
new file mode 100644
index 0000000000..533142b22a
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
@@ -0,0 +1,49 @@
1From 21a204147b16539b3eda3143b32844c49e29f4d4 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 11:33:49 +0000
4Subject: [PATCH] gvariant: Propagate trust when getting a child of a
5 serialised variant
6
7If a variant is trusted, that means all its children are trusted, so
8ensure that their checked offsets are set as such.
9
10This allows a lot of the offset table checks to be avoided when getting
11children from trusted serialised tuples, which speeds things up.
12
13No unit test is included because this is just a performance fix. If
14there are other slownesses, or regressions, in serialised `GVariant`
15performance, the fuzzing setup will catch them like it did this one.
16
17This change does reduce the time to run the oss-fuzz reproducer from 80s
18to about 0.7s on my machine.
19
20Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
21
22Fixes: #2841
23oss-fuzz#54314
24
25CVE: CVE-2023-32636
26Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/21a204147b16539b3eda3143b32844c49e29f4d4]
27Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
28---
29 glib/gvariant-core.c | 4 ++--
30 1 file changed, 2 insertions(+), 2 deletions(-)
31
32diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
33index 1b9d5cc..ed57c70 100644
34--- a/glib/gvariant-core.c
35+++ b/glib/gvariant-core.c
36@@ -1173,8 +1173,8 @@ g_variant_get_child_value (GVariant *value,
37 child->contents.serialised.bytes =
38 g_bytes_ref (value->contents.serialised.bytes);
39 child->contents.serialised.data = s_child.data;
40- child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
41- child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
42+ child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to;
43+ child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to;
44
45 return child;
46 }
47--
482.24.4
49
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
new file mode 100644
index 0000000000..9c0867bf5f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
@@ -0,0 +1,154 @@
1From 78da5faccb3e065116b75b3ff87ff55381da6c76 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 11:24:43 +0000
4Subject: [PATCH] gvariant: Check offset table doesn't fall outside variant
5 bounds
6
7When dereferencing the first entry in the offset table for a tuple,
8check that it doesn’t fall outside the bounds of the variant first.
9
10This prevents an out-of-bounds read from some non-normal tuples.
11
12This bug was introduced in commit 73d0aa81c2575a5c9ae77d.
13
14Includes a unit test, although the test will likely only catch the
15original bug if run with asan enabled.
16
17Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
18
19Fixes: #2840
20oss-fuzz#54302
21
22CVE: CVE-2023-32643
23Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/78da5faccb3e065116b75b3ff87ff55381da6c76]
24Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
25---
26 glib/gvariant-serialiser.c | 12 ++++++--
27 glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++
28 2 files changed, 72 insertions(+), 3 deletions(-)
29
30diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
31index 5aa2cbc..4e50ed7 100644
32--- a/glib/gvariant-serialiser.c
33+++ b/glib/gvariant-serialiser.c
34@@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
35
36 member_info = g_variant_type_info_member_info (value.type_info, index_);
37
38- if (member_info->i + 1)
39+ if (member_info->i + 1 &&
40+ offset_size * (member_info->i + 1) <= value.size)
41 member_start = gvs_read_unaligned_le (value.data + value.size -
42 offset_size * (member_info->i + 1),
43 offset_size);
44@@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
45 member_start &= member_info->b;
46 member_start |= member_info->c;
47
48- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
49+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST &&
50+ offset_size * (member_info->i + 1) <= value.size)
51 member_end = value.size - offset_size * (member_info->i + 1);
52
53 else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
54@@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
55 member_end = member_start + fixed_size;
56 }
57
58- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
59+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET &&
60+ offset_size * (member_info->i + 2) <= value.size)
61 member_end = gvs_read_unaligned_le (value.data + value.size -
62 offset_size * (member_info->i + 2),
63 offset_size);
64
65+ else /* invalid */
66+ member_end = G_MAXSIZE;
67+
68 if (out_member_start != NULL)
69 *out_member_start = member_start;
70 if (out_member_end != NULL)
71diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
72index 679dd40..2eca8be 100644
73--- a/glib/tests/gvariant.c
74+++ b/glib/tests/gvariant.c
75@@ -5432,6 +5432,67 @@ test_normal_checking_tuple_offsets4 (void)
76 g_variant_unref (variant);
77 }
78
79+/* This is a regression test that dereferencing the first element in the offset
80+ * table doesn’t dereference memory before the start of the GVariant. The first
81+ * element in the offset table gives the offset of the final member in the
82+ * tuple (the offset table is stored in reverse), and the position of this final
83+ * member is needed to check that none of the tuple members overlap with the
84+ * offset table
85+ *
86+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
87+static void
88+test_normal_checking_tuple_offsets5 (void)
89+{
90+ /* A tuple of type (sss) in normal form would have an offset table with two
91+ * entries:
92+ * - The first entry (lowest index in the table) gives the offset of the
93+ * third `s` in the tuple, as the offset table is reversed compared to the
94+ * tuple members.
95+ * - The second entry (highest index in the table) gives the offset of the
96+ * second `s` in the tuple.
97+ * - The offset of the first `s` in the tuple is always 0.
98+ *
99+ * See §2.5.4 (Structures) of the GVariant specification for details, noting
100+ * that the table is only layed out this way because all three members of the
101+ * tuple have non-fixed sizes.
102+ *
103+ * It’s not clear whether the 0xaa data of this variant is part of the strings
104+ * in the tuple, or part of the offset table. It doesn’t really matter. This
105+ * is a regression test to check that the code to validate the offset table
106+ * doesn’t unconditionally try to access the first entry in the offset table
107+ * by subtracting the table size from the end of the GVariant data.
108+ *
109+ * In this non-normal case, that would result in an address off the start of
110+ * the GVariant data, and an out-of-bounds read, because the GVariant is one
111+ * byte long, but the offset table is calculated as two bytes long (with 1B
112+ * sized entries) from the tuple’s type.
113+ */
114+ const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
115+ const guint8 data[] = { 0xaa };
116+ gsize size = sizeof (data);
117+ GVariant *variant = NULL;
118+ GVariant *normal_variant = NULL;
119+ GVariant *expected = NULL;
120+
121+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
122+
123+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
124+ g_assert_nonnull (variant);
125+
126+ g_assert_false (g_variant_is_normal_form (variant));
127+
128+ normal_variant = g_variant_get_normal_form (variant);
129+ g_assert_nonnull (normal_variant);
130+
131+ expected = g_variant_new_parsed ("('', '', '')");
132+ g_assert_cmpvariant (expected, variant);
133+ g_assert_cmpvariant (expected, normal_variant);
134+
135+ g_variant_unref (expected);
136+ g_variant_unref (normal_variant);
137+ g_variant_unref (variant);
138+}
139+
140 /* Test that an otherwise-valid serialised GVariant is considered non-normal if
141 * its offset table entries are too wide.
142 *
143@@ -5680,6 +5741,8 @@ main (int argc, char **argv)
144 test_normal_checking_tuple_offsets3);
145 g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
146 test_normal_checking_tuple_offsets4);
147+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
148+ test_normal_checking_tuple_offsets5);
149 g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
150 test_normal_checking_tuple_offsets_minimal_sized);
151 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
152--
1532.24.4
154
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
new file mode 100644
index 0000000000..9fc58341cb
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
@@ -0,0 +1,103 @@
1From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:04:49 +0000
4Subject: [PATCH] gvariant-core: Consolidate construction of
5 `GVariantSerialised`
6
7So I only need to change it in one place.
8
9This introduces no functional changes.
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
15Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
16---
17 glib/gvariant-core.c | 49 ++++++++++++++++++++++----------------------
18 1 file changed, 25 insertions(+), 24 deletions(-)
19
20diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
21index 9397573..aa0e0a0 100644
22--- a/glib/gvariant-core.c
23+++ b/glib/gvariant-core.c
24@@ -349,6 +349,27 @@ g_variant_ensure_size (GVariant *value)
25 }
26 }
27
28+/* < private >
29+ * g_variant_to_serialised:
30+ * @value: a #GVariant
31+ *
32+ * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED.
33+ */
34+inline static GVariantSerialised
35+g_variant_to_serialised (GVariant *value)
36+{
37+ g_assert (value->state & STATE_SERIALISED);
38+ {
39+ GVariantSerialised serialised = {
40+ value->type_info,
41+ (gpointer) value->contents.serialised.data,
42+ value->size,
43+ value->depth,
44+ };
45+ return serialised;
46+ }
47+}
48+
49 /* < private >
50 * g_variant_serialise:
51 * @value: a #GVariant
52@@ -991,16 +1012,8 @@ g_variant_n_children (GVariant *value)
53 g_variant_lock (value);
54
55 if (value->state & STATE_SERIALISED)
56- {
57- GVariantSerialised serialised = {
58- value->type_info,
59- (gpointer) value->contents.serialised.data,
60- value->size,
61- value->depth,
62- };
63-
64- n_children = g_variant_serialised_n_children (serialised);
65- }
66+ n_children = g_variant_serialised_n_children (
67+ g_variant_to_serialised (value));
68 else
69 n_children = value->contents.tree.n_children;
70
71@@ -1061,12 +1074,7 @@ g_variant_get_child_value (GVariant *value,
72 }
73
74 {
75- GVariantSerialised serialised = {
76- value->type_info,
77- (gpointer) value->contents.serialised.data,
78- value->size,
79- value->depth,
80- };
81+ GVariantSerialised serialised = g_variant_to_serialised (value);
82 GVariantSerialised s_child;
83 GVariant *child;
84
85@@ -1179,14 +1187,7 @@ g_variant_is_normal_form (GVariant *value)
86
87 if (value->state & STATE_SERIALISED)
88 {
89- GVariantSerialised serialised = {
90- value->type_info,
91- (gpointer) value->contents.serialised.data,
92- value->size,
93- value->depth
94- };
95-
96- if (g_variant_serialised_is_normal (serialised))
97+ if (g_variant_serialised_is_normal (g_variant_to_serialised (value)))
98 value->state |= STATE_TRUSTED;
99 }
100 else
101--
1022.24.4
103
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
new file mode 100644
index 0000000000..0e96b8d457
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
@@ -0,0 +1,210 @@
1From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 9 Aug 2023 10:39:34 +0000
4Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
5 framing offsets
6
7This introduces no functional changes.
8
9Helps: #2121
10
11CVE: CVE-2023-32665
12Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
13Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
14---
15 glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------
16 1 file changed, 57 insertions(+), 51 deletions(-)
17
18diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
19index 83e9d85..c7c2114 100644
20--- a/glib/gvariant-serialiser.c
21+++ b/glib/gvariant-serialiser.c
22@@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_size,
23 return body_size + 8 * offsets;
24 }
25
26+struct Offsets
27+{
28+ gsize data_size;
29+
30+ guchar *array;
31+ gsize length;
32+ guint offset_size;
33+
34+ gboolean is_normal;
35+};
36+
37 static gsize
38-gvs_variable_sized_array_n_children (GVariantSerialised value)
39+gvs_offsets_get_offset_n (struct Offsets *offsets,
40+ gsize n)
41+{
42+ return gvs_read_unaligned_le (
43+ offsets->array + (offsets->offset_size * n), offsets->offset_size);
44+}
45+
46+static struct Offsets
47+gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
48 {
49+ struct Offsets out = { 0, };
50 gsize offsets_array_size;
51- gsize offset_size;
52 gsize last_end;
53
54 if (value.size == 0)
55- return 0;
56-
57- offset_size = gvs_get_offset_size (value.size);
58+ {
59+ out.is_normal = TRUE;
60+ return out;
61+ }
62
63- last_end = gvs_read_unaligned_le (value.data + value.size -
64- offset_size, offset_size);
65+ out.offset_size = gvs_get_offset_size (value.size);
66+ last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
67+ out.offset_size);
68
69 if (last_end > value.size)
70- return 0;
71+ return out; /* offsets not normal */
72
73 offsets_array_size = value.size - last_end;
74
75- if (offsets_array_size % offset_size)
76- return 0;
77+ if (offsets_array_size % out.offset_size)
78+ return out; /* offsets not normal */
79+
80+ out.data_size = last_end;
81+ out.array = value.data + last_end;
82+ out.length = offsets_array_size / out.offset_size;
83+ out.is_normal = TRUE;
84
85- return offsets_array_size / offset_size;
86+ return out;
87+}
88+
89+static gsize
90+gvs_variable_sized_array_n_children (GVariantSerialised value)
91+{
92+ return gvs_variable_sized_array_get_frame_offsets (value).length;
93 }
94
95 static GVariantSerialised
96@@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
97 gsize index_)
98 {
99 GVariantSerialised child = { 0, };
100- gsize offset_size;
101- gsize last_end;
102+
103+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
104+
105 gsize start;
106 gsize end;
107
108@@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
109 g_variant_type_info_ref (child.type_info);
110 child.depth = value.depth + 1;
111
112- offset_size = gvs_get_offset_size (value.size);
113-
114- last_end = gvs_read_unaligned_le (value.data + value.size -
115- offset_size, offset_size);
116-
117 if (index_ > 0)
118 {
119 guint alignment;
120
121- start = gvs_read_unaligned_le (value.data + last_end +
122- (offset_size * (index_ - 1)),
123- offset_size);
124+ start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
125
126 g_variant_type_info_query (child.type_info, &alignment, NULL);
127 start += (-start) & alignment;
128@@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
129 else
130 start = 0;
131
132- end = gvs_read_unaligned_le (value.data + last_end +
133- (offset_size * index_),
134- offset_size);
135+ end = gvs_offsets_get_offset_n (&offsets, index_);
136
137- if (start < end && end <= value.size && end <= last_end)
138+ if (start < end && end <= value.size && end <= offsets.data_size)
139 {
140 child.data = value.data + start;
141 child.size = end - start;
142@@ -768,34 +792,16 @@ static gboolean
143 gvs_variable_sized_array_is_normal (GVariantSerialised value)
144 {
145 GVariantSerialised child = { 0, };
146- gsize offsets_array_size;
147- guchar *offsets_array;
148- guint offset_size;
149 guint alignment;
150- gsize last_end;
151- gsize length;
152 gsize offset;
153 gsize i;
154
155- if (value.size == 0)
156- return TRUE;
157-
158- offset_size = gvs_get_offset_size (value.size);
159- last_end = gvs_read_unaligned_le (value.data + value.size -
160- offset_size, offset_size);
161+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
162
163- if (last_end > value.size)
164+ if (!offsets.is_normal)
165 return FALSE;
166
167- offsets_array_size = value.size - last_end;
168-
169- if (offsets_array_size % offset_size)
170- return FALSE;
171-
172- offsets_array = value.data + value.size - offsets_array_size;
173- length = offsets_array_size / offset_size;
174-
175- if (length == 0)
176+ if (value.size != 0 && offsets.length == 0)
177 return FALSE;
178
179 child.type_info = g_variant_type_info_element (value.type_info);
180@@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
181 child.depth = value.depth + 1;
182 offset = 0;
183
184- for (i = 0; i < length; i++)
185+ for (i = 0; i < offsets.length; i++)
186 {
187 gsize this_end;
188
189- this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
190- offset_size);
191+ this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
192+ offsets.offset_size);
193
194- if (this_end < offset || this_end > last_end)
195+ if (this_end < offset || this_end > offsets.data_size)
196 return FALSE;
197
198 while (offset & alignment)
199@@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
200 offset = this_end;
201 }
202
203- g_assert (offset == last_end);
204+ g_assert (offset == offsets.data_size);
205
206 return TRUE;
207 }
208--
2092.24.4
210
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
new file mode 100644
index 0000000000..e361cc7aad
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
@@ -0,0 +1,417 @@
1From ade71fb544391b2e33e1859645726bfee0d5eaaf Mon Sep 17 00:00:00 2001
2From: William Manley <will@stb-tester.com>
3Date: Wed, 16 Aug 2023 03:12:21 +0000
4Subject: [PATCH] gvariant: Don't allow child elements to overlap with each
5 other
6
7If different elements of a variable sized array can overlap with each
8other then we can cause a `GVariant` to normalise to a much larger type.
9
10This commit changes the behaviour of `GVariant` with non-normal form data. If
11an invalid frame offset is found all subsequent elements are given their
12default value.
13
14When retrieving an element at index `n` we scan the frame offsets up to index
15`n` and if they are not in order we return an element with the default value
16for that type. This guarantees that elements don't overlap with each
17other. We remember the offset we've scanned up to so we don't need to
18repeat this work on subsequent accesses. We skip these checks for trusted
19data.
20
21Unfortunately this makes random access of untrusted data O(n) — at least
22on first access. It doesn't affect the algorithmic complexity of accessing
23elements in order, such as when using the `GVariantIter` interface. Also:
24the cost of validation will be amortised as the `GVariant` instance is
25continued to be used.
26
27I've implemented this with 4 different functions, 1 for each element size,
28rather than looping calling `gvs_read_unaligned_le` in the hope that the
29compiler will find it easy to optimise and should produce fairly tight
30code.
31
32Fixes: #2121
33
34CVE: CVE-2023-32665
35Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/ade71fb544391b2e33e1859645726bfee0d5eaaf]
36Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
37---
38 glib/gvariant-core.c | 35 ++++++++++++++++
39 glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++--
40 glib/gvariant-serialiser.h | 8 ++++
41 glib/tests/gvariant.c | 45 ++++++++++++++++++++
42 4 files changed, 171 insertions(+), 3 deletions(-)
43
44diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
45index aa0e0a0..9b51e15 100644
46--- a/glib/gvariant-core.c
47+++ b/glib/gvariant-core.c
48@@ -65,6 +65,7 @@ struct _GVariant
49 {
50 GBytes *bytes;
51 gconstpointer data;
52+ gsize ordered_offsets_up_to;
53 } serialised;
54
55 struct
56@@ -162,6 +163,24 @@ struct _GVariant
57 * if .data pointed to the appropriate number of nul
58 * bytes.
59 *
60+ * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all
61+ * the frame offsets up to and including the frame
62+ * offset determining the end of element n are in
63+ * order. This guarantees that the bytes of element
64+ * n don't overlap with any previous element.
65+ *
66+ * For trusted data this is set to G_MAXSIZE and we
67+ * don't check that the frame offsets are in order.
68+ *
69+ * Note: This doesn't imply the offsets are good in
70+ * any way apart from their ordering. In particular
71+ * offsets may be out of bounds for this value or
72+ * may imply that the data overlaps the frame
73+ * offsets themselves.
74+ *
75+ * This field is only relevant for arrays of non
76+ * fixed width types.
77+ *
78 * .tree: Only valid when the instance is in tree form.
79 *
80 * Note that accesses from other threads could result in
81@@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value)
82 (gpointer) value->contents.serialised.data,
83 value->size,
84 value->depth,
85+ value->contents.serialised.ordered_offsets_up_to,
86 };
87 return serialised;
88 }
89@@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value,
90 serialised.size = value->size;
91 serialised.data = data;
92 serialised.depth = value->depth;
93+ serialised.ordered_offsets_up_to = 0;
94
95 children = (gpointer *) value->contents.tree.children;
96 n_children = value->contents.tree.n_children;
97@@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
98 g_assert (serialised->size == value->size);
99 serialised->depth = value->depth;
100
101+ if (value->state & STATE_SERIALISED)
102+ {
103+ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
104+ }
105+ else
106+ {
107+ serialised->ordered_offsets_up_to = 0;
108+ }
109+
110 if (serialised->data)
111 /* g_variant_store() is a public API, so it
112 * it will reacquire the lock if it needs to.
113@@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *value)
114 bytes = g_bytes_new_take (data, value->size);
115 value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
116 value->contents.serialised.bytes = bytes;
117+ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
118 value->state |= STATE_SERIALISED;
119 }
120 }
121@@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariantType *type,
122 serialised.type_info = value->type_info;
123 serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
124 serialised.depth = 0;
125+ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
126
127 if (!g_variant_serialised_check (serialised))
128 {
129@@ -610,6 +642,8 @@ g_variant_new_from_bytes (const GVariantType *type,
130 value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
131 }
132
133+ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
134+
135 g_clear_pointer (&owned_bytes, g_bytes_unref);
136
137 return value;
138@@ -1108,6 +1142,7 @@ g_variant_get_child_value (GVariant *value,
139 child->contents.serialised.bytes =
140 g_bytes_ref (value->contents.serialised.bytes);
141 child->contents.serialised.data = s_child.data;
142+ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
143
144 return child;
145 }
146diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
147index c7c2114..fe0b1a4 100644
148--- a/glib/gvariant-serialiser.c
149+++ b/glib/gvariant-serialiser.c
150@@ -1,6 +1,7 @@
151 /*
152 * Copyright © 2007, 2008 Ryan Lortie
153 * Copyright © 2010 Codethink Limited
154+ * Copyright © 2020 William Manley
155 *
156 * This library is free software; you can redistribute it and/or
157 * modify it under the terms of the GNU Lesser General Public
158@@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
159 value.type_info = g_variant_type_info_element (value.type_info);
160 g_variant_type_info_ref (value.type_info);
161 value.depth++;
162+ value.ordered_offsets_up_to = 0;
163
164 return value;
165 }
166@@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
167 {
168 if (n_children)
169 {
170- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 };
171+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
172
173 gvs_filler (&child, children[0]);
174 }
175@@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
176 /* proper element size: "Just". recurse to the child. */
177 value.type_info = g_variant_type_info_element (value.type_info);
178 value.depth++;
179+ value.ordered_offsets_up_to = 0;
180
181 return g_variant_serialised_is_normal (value);
182 }
183@@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
184 value.data = NULL;
185
186 value.depth++;
187+ value.ordered_offsets_up_to = 0;
188
189 return value;
190 }
191@@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
192 {
193 if (n_children)
194 {
195- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 };
196+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
197
198 /* write the data for the child. */
199 gvs_filler (&child, children[0]);
200@@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
201 value.type_info = g_variant_type_info_element (value.type_info);
202 value.size--;
203 value.depth++;
204+ value.ordered_offsets_up_to = 0;
205
206 return g_variant_serialised_is_normal (value);
207 }
208@@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVariantSerialised value)
209 return gvs_variable_sized_array_get_frame_offsets (value).length;
210 }
211
212+/* Find the index of the first out-of-order element in @data, assuming that
213+ * @data is an array of elements of given @type, starting at index @start and
214+ * containing a further @len-@start elements. */
215+#define DEFINE_FIND_UNORDERED(type) \
216+ static gsize \
217+ find_unordered_##type (const guint8 *data, gsize start, gsize len) \
218+ { \
219+ gsize off; \
220+ type current, previous; \
221+ \
222+ memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
223+ for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
224+ { \
225+ memcpy (&current, data + off, sizeof (current)); \
226+ if (current < previous) \
227+ break; \
228+ previous = current; \
229+ } \
230+ return off / sizeof (current) - 1; \
231+ }
232+
233+DEFINE_FIND_UNORDERED (guint8);
234+DEFINE_FIND_UNORDERED (guint16);
235+DEFINE_FIND_UNORDERED (guint32);
236+DEFINE_FIND_UNORDERED (guint64);
237+
238 static GVariantSerialised
239 gvs_variable_sized_array_get_child (GVariantSerialised value,
240 gsize index_)
241@@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
242 g_variant_type_info_ref (child.type_info);
243 child.depth = value.depth + 1;
244
245+ /* If the requested @index_ is beyond the set of indices whose framing offsets
246+ * have been checked, check the remaining offsets to see whether they’re
247+ * normal (in order, no overlapping array elements). */
248+ if (index_ > value.ordered_offsets_up_to)
249+ {
250+ switch (offsets.offset_size)
251+ {
252+ case 1:
253+ {
254+ value.ordered_offsets_up_to = find_unordered_guint8 (
255+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
256+ break;
257+ }
258+ case 2:
259+ {
260+ value.ordered_offsets_up_to = find_unordered_guint16 (
261+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
262+ break;
263+ }
264+ case 4:
265+ {
266+ value.ordered_offsets_up_to = find_unordered_guint32 (
267+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
268+ break;
269+ }
270+ case 8:
271+ {
272+ value.ordered_offsets_up_to = find_unordered_guint64 (
273+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
274+ break;
275+ }
276+ default:
277+ /* gvs_get_offset_size() only returns maximum 8 */
278+ g_assert_not_reached ();
279+ }
280+ }
281+
282+ if (index_ > value.ordered_offsets_up_to)
283+ {
284+ /* Offsets are invalid somewhere, so return an empty child. */
285+ return child;
286+ }
287+
288 if (index_ > 0)
289 {
290 guint alignment;
291@@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
292
293 g_assert (offset == offsets.data_size);
294
295+ /* All offsets have now been checked. */
296+ value.ordered_offsets_up_to = G_MAXSIZE;
297+
298 return TRUE;
299 }
300
301@@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
302 for (i = 0; i < length; i++)
303 {
304 const GVariantMemberInfo *member_info;
305- GVariantSerialised child;
306+ GVariantSerialised child = { 0, };
307 gsize fixed_size;
308 guint alignment;
309 gsize end;
310@@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised value)
311 offset = end;
312 }
313
314+ /* All element bounds have been checked above. */
315+ value.ordered_offsets_up_to = G_MAXSIZE;
316+
317 {
318 gsize fixed_size;
319 guint alignment;
320diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
321index 81343e9..99d18ef 100644
322--- a/glib/gvariant-serialiser.h
323+++ b/glib/gvariant-serialiser.h
324@@ -29,6 +29,14 @@ typedef struct
325 guchar *data;
326 gsize size;
327 gsize depth; /* same semantics as GVariant.depth */
328+ /* If ordered_offsets_up_to == n this means that all the frame offsets up to and
329+ * including the frame offset determining the end of element n are in order.
330+ * This guarantees that the bytes of element n don't overlap with any previous
331+ * element.
332+ *
333+ * This is both read and set by g_variant_serialised_get_child for arrays of
334+ * non-fixed-width types */
335+ gsize ordered_offsets_up_to;
336 } GVariantSerialised;
337
338 /* deserialisation */
339diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
340index 0e5ec8e..967e9a1 100644
341--- a/glib/tests/gvariant.c
342+++ b/glib/tests/gvariant.c
343@@ -1,5 +1,6 @@
344 /*
345 * Copyright © 2010 Codethink Limited
346+ * Copyright © 2020 William Manley
347 *
348 * This library is free software; you can redistribute it and/or
349 * modify it under the terms of the GNU Lesser General Public
350@@ -1283,6 +1284,7 @@ random_instance_filler (GVariantSerialised *serialised,
351 serialised->size = instance->size;
352
353 serialised->depth = 0;
354+ serialised->ordered_offsets_up_to = 0;
355
356 g_assert_true (serialised->type_info == instance->type_info);
357 g_assert_cmpuint (serialised->size, ==, instance->size);
358@@ -5039,6 +5041,47 @@ test_normal_checking_array_offsets (void)
359 g_variant_unref (variant);
360 }
361
362+/* This is a regression test that we can't have non-normal values that take up
363+ * significantly more space than the normal equivalent, by specifying the
364+ * offset table entries so that array elements overlap.
365+ *
366+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
367+static void
368+test_normal_checking_array_offsets2 (void)
369+{
370+ const guint8 data[] = {
371+ 'h', 'i', '\0',
372+ 0x03, 0x00, 0x03,
373+ 0x06, 0x00, 0x06,
374+ 0x09, 0x00, 0x09,
375+ 0x0c, 0x00, 0x0c,
376+ 0x0f, 0x00, 0x0f,
377+ 0x12, 0x00, 0x12,
378+ 0x15, 0x00, 0x15,
379+ };
380+ gsize size = sizeof (data);
381+ const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
382+ GVariant *variant = NULL;
383+ GVariant *normal_variant = NULL;
384+ GVariant *expected = NULL;
385+
386+ variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
387+ g_assert_nonnull (variant);
388+
389+ normal_variant = g_variant_get_normal_form (variant);
390+ g_assert_nonnull (normal_variant);
391+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
392+
393+ expected = g_variant_new_parsed (
394+ "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
395+ g_assert_cmpvariant (expected, variant);
396+ g_assert_cmpvariant (expected, normal_variant);
397+
398+ g_variant_unref (expected);
399+ g_variant_unref (normal_variant);
400+ g_variant_unref (variant);
401+}
402+
403 /* Test that a tuple with invalidly large values in its offset table is
404 * normalised successfully without looping infinitely. */
405 static void
406@@ -5206,6 +5249,8 @@ main (int argc, char **argv)
407 test_normal_checking_tuples);
408 g_test_add_func ("/gvariant/normal-checking/array-offsets",
409 test_normal_checking_array_offsets);
410+ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
411+ test_normal_checking_array_offsets2);
412 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
413 test_normal_checking_tuple_offsets);
414 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
415--
4162.24.4
417
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
new file mode 100644
index 0000000000..c057729aae
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
@@ -0,0 +1,113 @@
1From 345cae9c1aa7bf6752039225ef4c8d8d69fa8d76 Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Fri, 11 Aug 2023 04:09:12 +0000
4Subject: [PATCH] gvariant-serialiser: Factor out code to get bounds of a tuple
5 member
6
7This introduces no functional changes.
8
9Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/345cae9c1aa7bf6752039225ef4c8d8d69fa8d76]
15Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
16---
17 glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++--------------
18 1 file changed, 46 insertions(+), 27 deletions(-)
19
20diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
21index fe0b1a4..6f9b366 100644
22--- a/glib/gvariant-serialiser.c
23+++ b/glib/gvariant-serialiser.c
24@@ -942,6 +942,51 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
25 * for the tuple. See the notes in gvarianttypeinfo.h.
26 */
27
28+static void
29+gvs_tuple_get_member_bounds (GVariantSerialised value,
30+ gsize index_,
31+ gsize offset_size,
32+ gsize *out_member_start,
33+ gsize *out_member_end)
34+{
35+ const GVariantMemberInfo *member_info;
36+ gsize member_start, member_end;
37+
38+ member_info = g_variant_type_info_member_info (value.type_info, index_);
39+
40+ if (member_info->i + 1)
41+ member_start = gvs_read_unaligned_le (value.data + value.size -
42+ offset_size * (member_info->i + 1),
43+ offset_size);
44+ else
45+ member_start = 0;
46+
47+ member_start += member_info->a;
48+ member_start &= member_info->b;
49+ member_start |= member_info->c;
50+
51+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
52+ member_end = value.size - offset_size * (member_info->i + 1);
53+
54+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
55+ {
56+ gsize fixed_size;
57+
58+ g_variant_type_info_query (member_info->type_info, NULL, &fixed_size);
59+ member_end = member_start + fixed_size;
60+ }
61+
62+ else /* G_VARIANT_MEMBER_ENDING_OFFSET */
63+ member_end = gvs_read_unaligned_le (value.data + value.size -
64+ offset_size * (member_info->i + 2),
65+ offset_size);
66+
67+ if (out_member_start != NULL)
68+ *out_member_start = member_start;
69+ if (out_member_end != NULL)
70+ *out_member_end = member_end;
71+}
72+
73 static gsize
74 gvs_tuple_n_children (GVariantSerialised value)
75 {
76@@ -997,33 +1042,7 @@ gvs_tuple_get_child (GVariantSerialised value,
77 }
78 }
79
80- if (member_info->i + 1)
81- start = gvs_read_unaligned_le (value.data + value.size -
82- offset_size * (member_info->i + 1),
83- offset_size);
84- else
85- start = 0;
86-
87- start += member_info->a;
88- start &= member_info->b;
89- start |= member_info->c;
90-
91- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
92- end = value.size - offset_size * (member_info->i + 1);
93-
94- else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
95- {
96- gsize fixed_size;
97-
98- g_variant_type_info_query (child.type_info, NULL, &fixed_size);
99- end = start + fixed_size;
100- child.size = fixed_size;
101- }
102-
103- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
104- end = gvs_read_unaligned_le (value.data + value.size -
105- offset_size * (member_info->i + 2),
106- offset_size);
107+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
108
109 /* The child should not extend into the offset table. */
110 if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
111--
1122.24.4
113
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch
new file mode 100644
index 0000000000..7e516b07ab
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0005.patch
@@ -0,0 +1,80 @@
1From 73d0aa81c2575a5c9ae77dcb94da919579014fc0 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Fri, 11 Aug 2023 04:13:02 +0000
4Subject: [PATCH] gvariant-serialiser: Rework child size calculation
5
6This reduces a few duplicate calls to `g_variant_type_info_query()` and
7explains why they’re needed.
8
9Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
10
11Helps: #2121
12
13CVE: CVE-2023-32665
14Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/73d0aa81c2575a5c9ae77dcb94da919579014fc0]
15Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
16---
17 glib/gvariant-serialiser.c | 31 +++++++++----------------------
18 1 file changed, 9 insertions(+), 22 deletions(-)
19
20diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
21index 6f9b366..fb75923 100644
22--- a/glib/gvariant-serialiser.c
23+++ b/glib/gvariant-serialiser.c
24@@ -1007,14 +1007,18 @@ gvs_tuple_get_child (GVariantSerialised value,
25 child.depth = value.depth + 1;
26 offset_size = gvs_get_offset_size (value.size);
27
28+ /* Ensure the size is set for fixed-sized children, or
29+ * g_variant_serialised_check() will fail, even if we return
30+ * (child.data == NULL) to indicate an error. */
31+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
32+ g_variant_type_info_query (child.type_info, NULL, &child.size);
33+
34 /* tuples are the only (potentially) fixed-sized containers, so the
35 * only ones that have to deal with the possibility of having %NULL
36 * data with a non-zero %size if errors occurred elsewhere.
37 */
38 if G_UNLIKELY (value.data == NULL && value.size != 0)
39 {
40- g_variant_type_info_query (child.type_info, NULL, &child.size);
41-
42 /* this can only happen in fixed-sized tuples,
43 * so the child must also be fixed sized.
44 */
45@@ -1032,29 +1036,12 @@ gvs_tuple_get_child (GVariantSerialised value,
46 else
47 {
48 if (offset_size * (member_info->i + 1) > value.size)
49- {
50- /* if the child is fixed size, return its size.
51- * if child is not fixed-sized, return size = 0.
52- */
53- g_variant_type_info_query (child.type_info, NULL, &child.size);
54-
55- return child;
56- }
57+ return child;
58 }
59
60- gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
61-
62 /* The child should not extend into the offset table. */
63- if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
64- {
65- GVariantSerialised last_child;
66- last_child = gvs_tuple_get_child (value,
67- g_variant_type_info_n_members (value.type_info) - 1);
68- last_end = last_child.data + last_child.size - value.data;
69- g_variant_type_info_unref (last_child.type_info);
70- }
71- else
72- last_end = end;
73+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
74+ gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end);
75
76 if (start < end && end <= value.size && end <= last_end)
77 {
78--
792.24.4
80
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
new file mode 100644
index 0000000000..8558a7911f
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
@@ -0,0 +1,396 @@
1From 7cf6f5b69146d20948d42f0c476688fe17fef787 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 16 Aug 2023 12:09:06 +0000
4Subject: [PATCH] gvariant: Don't allow child elements of a tuple to overlap
5 each other
6
7This is similar to the earlier commit which prevents child elements of a
8variable-sized array from overlapping each other, but this time for
9tuples. It is based heavily on ideas by William Manley.
10
11Tuples are slightly different from variable-sized arrays in that they
12contain a mixture of fixed and variable sized elements. All but one of
13the variable sized elements have an entry in the frame offsets table.
14This means that if we were to just check the ordering of the frame
15offsets table, the variable sized elements could still overlap
16interleaving fixed sized elements, which would be bad.
17
18Therefore we have to check the elements rather than the frame offsets.
19
20The logic of checking the elements up to the index currently being
21requested, and caching the result in `ordered_offsets_up_to`, means that
22the algorithmic cost implications are the same for this commit as for
23variable-sized arrays: an O(N) cost for these checks is amortised out
24over N accesses to O(1) per access.
25
26Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
27
28Fixes: #2121
29
30CVE: CVE-2023-32665
31Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/7cf6f5b69146d20948d42f0c476688fe17fef787]
32Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
33---
34 glib/gvariant-core.c | 6 +-
35 glib/gvariant-serialiser.c | 40 ++++++++
36 glib/gvariant-serialiser.h | 7 +-
37 glib/gvariant.c | 1 +
38 glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++
39 5 files changed, 232 insertions(+), 3 deletions(-)
40
41diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
42index 9b51e15..b951cd9 100644
43--- a/glib/gvariant-core.c
44+++ b/glib/gvariant-core.c
45@@ -1,6 +1,7 @@
46 /*
47 * Copyright © 2007, 2008 Ryan Lortie
48 * Copyright © 2010 Codethink Limited
49+ * Copyright © 2022 Endless OS Foundation, LLC
50 *
51 * This library is free software; you can redistribute it and/or
52 * modify it under the terms of the GNU Lesser General Public
53@@ -179,7 +180,7 @@ struct _GVariant
54 * offsets themselves.
55 *
56 * This field is only relevant for arrays of non
57- * fixed width types.
58+ * fixed width types and for tuples.
59 *
60 * .tree: Only valid when the instance is in tree form.
61 *
62@@ -1117,6 +1118,9 @@ g_variant_get_child_value (GVariant *value,
63 */
64 s_child = g_variant_serialised_get_child (serialised, index_);
65
66+ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
67+ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
68+
69 /* Check whether this would cause nesting too deep. If so, return a fake
70 * child. The only situation we expect this to happen in is with a variant,
71 * as all other deeply-nested types have a static type, and hence should
72diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
73index fb75923..cd4a3e6 100644
74--- a/glib/gvariant-serialiser.c
75+++ b/glib/gvariant-serialiser.c
76@@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
77 * for the tuple. See the notes in gvarianttypeinfo.h.
78 */
79
80+/* Note: This doesn’t guarantee that @out_member_end >= @out_member_start; that
81+ * condition may not hold true for invalid serialised variants. The caller is
82+ * responsible for checking the returned values and handling invalid ones
83+ * appropriately. */
84 static void
85 gvs_tuple_get_member_bounds (GVariantSerialised value,
86 gsize index_,
87@@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised value,
88 return child;
89 }
90
91+ /* If the requested @index_ is beyond the set of indices whose framing offsets
92+ * have been checked, check the remaining offsets to see whether they’re
93+ * normal (in order, no overlapping tuple elements).
94+ *
95+ * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check
96+ * all the tuple *elements* here, not just all the framing offsets, since
97+ * tuples contain a mix of elements which use framing offsets and ones which
98+ * don’t. None of them are allowed to overlap. */
99+ if (index_ > value.ordered_offsets_up_to)
100+ {
101+ gsize i, prev_i_end = 0;
102+
103+ if (value.ordered_offsets_up_to > 0)
104+ gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
105+
106+ for (i = value.ordered_offsets_up_to; i <= index_; i++)
107+ {
108+ gsize i_start, i_end;
109+
110+ gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end);
111+
112+ if (i_start > i_end || i_start < prev_i_end || i_end > value.size)
113+ break;
114+
115+ prev_i_end = i_end;
116+ }
117+
118+ value.ordered_offsets_up_to = i - 1;
119+ }
120+
121+ if (index_ > value.ordered_offsets_up_to)
122+ {
123+ /* Offsets are invalid somewhere, so return an empty child. */
124+ return child;
125+ }
126+
127 if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
128 {
129 if (offset_size * (member_info->i + 2) > value.size)
130diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
131index 99d18ef..144aec8 100644
132--- a/glib/gvariant-serialiser.h
133+++ b/glib/gvariant-serialiser.h
134@@ -34,8 +34,11 @@ typedef struct
135 * This guarantees that the bytes of element n don't overlap with any previous
136 * element.
137 *
138- * This is both read and set by g_variant_serialised_get_child for arrays of
139- * non-fixed-width types */
140+ * This is both read and set by g_variant_serialised_get_child() for arrays of
141+ * non-fixed-width types, and for tuples.
142+ *
143+ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
144+ * rather than an index into the frame offsets. */
145 gsize ordered_offsets_up_to;
146 } GVariantSerialised;
147
148diff --git a/glib/gvariant.c b/glib/gvariant.c
149index d6f68a9..cdb428e 100644
150--- a/glib/gvariant.c
151+++ b/glib/gvariant.c
152@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
153 serialised.type_info = g_variant_get_type_info (trusted);
154 serialised.size = g_variant_get_size (trusted);
155 serialised.data = g_malloc (serialised.size);
156+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
157 g_variant_store (trusted, serialised.data);
158 g_variant_unref (trusted);
159
160diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
161index 967e9a1..a84b02e 100644
162--- a/glib/tests/gvariant.c
163+++ b/glib/tests/gvariant.c
164@@ -1,6 +1,7 @@
165 /*
166 * Copyright © 2010 Codethink Limited
167 * Copyright © 2020 William Manley
168+ * Copyright © 2022 Endless OS Foundation, LLC
169 *
170 * This library is free software; you can redistribute it and/or
171 * modify it under the terms of the GNU Lesser General Public
172@@ -1451,6 +1452,7 @@ test_maybe (void)
173 serialised.data = flavoured_malloc (needed_size, flavour);
174 serialised.size = needed_size;
175 serialised.depth = 0;
176+ serialised.ordered_offsets_up_to = 0;
177
178 g_variant_serialiser_serialise (serialised,
179 random_instance_filler,
180@@ -1574,6 +1576,7 @@ test_array (void)
181 serialised.data = flavoured_malloc (needed_size, flavour);
182 serialised.size = needed_size;
183 serialised.depth = 0;
184+ serialised.ordered_offsets_up_to = 0;
185
186 g_variant_serialiser_serialise (serialised, random_instance_filler,
187 (gpointer *) instances, n_children);
188@@ -1738,6 +1741,7 @@ test_tuple (void)
189 serialised.data = flavoured_malloc (needed_size, flavour);
190 serialised.size = needed_size;
191 serialised.depth = 0;
192+ serialised.ordered_offsets_up_to = 0;
193
194 g_variant_serialiser_serialise (serialised, random_instance_filler,
195 (gpointer *) instances, n_children);
196@@ -1834,6 +1838,7 @@ test_variant (void)
197 serialised.data = flavoured_malloc (needed_size, flavour);
198 serialised.size = needed_size;
199 serialised.depth = 0;
200+ serialised.ordered_offsets_up_to = 0;
201
202 g_variant_serialiser_serialise (serialised, random_instance_filler,
203 (gpointer *) &instance, 1);
204@@ -5106,6 +5111,176 @@ test_normal_checking_tuple_offsets (void)
205 g_variant_unref (variant);
206 }
207
208+/* This is a regression test that we can't have non-normal values that take up
209+ * significantly more space than the normal equivalent, by specifying the
210+ * offset table entries so that tuple elements overlap.
211+ *
212+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
213+ * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
214+static void
215+test_normal_checking_tuple_offsets2 (void)
216+{
217+ const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
218+ const guint8 data[] = {
219+ 0x12, 0x34, 0x56, 0x78, 0x01,
220+ /*
221+ ^───────────────────┘
222+
223+ ^^^^^^^^^^ 1st yy
224+ ^^^^^^^^^^ 2nd yy
225+ ^^^^^^^^^^ 3rd yy
226+ ^^^^ Framing offsets
227+ */
228+
229+ /* If this variant was encoded normally, it would be something like this:
230+ * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
231+ * ^─────────────────────────────────────────────────────┘
232+ *
233+ * ^^^^^^^^^^ 1st yy
234+ * ^^^^^^^^^^ 2nd yy
235+ * ^^^^^^^^^^ 3rd yy
236+ * ^^^^ Framing offsets
237+ */
238+ };
239+ gsize size = sizeof (data);
240+ GVariant *variant = NULL;
241+ GVariant *normal_variant = NULL;
242+ GVariant *expected = NULL;
243+
244+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
245+ g_assert_nonnull (variant);
246+
247+ normal_variant = g_variant_get_normal_form (variant);
248+ g_assert_nonnull (normal_variant);
249+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
250+
251+ expected = g_variant_new_parsed (
252+ "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
253+ g_assert_cmpvariant (expected, variant);
254+ g_assert_cmpvariant (expected, normal_variant);
255+
256+ g_variant_unref (expected);
257+ g_variant_unref (normal_variant);
258+ g_variant_unref (variant);
259+}
260+
261+/* This is a regression test that overlapping entries in the offset table are
262+ * decoded consistently, even though they’re non-normal.
263+ *
264+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
265+static void
266+test_normal_checking_tuple_offsets3 (void)
267+{
268+ /* The expected decoding of this non-normal byte stream is complex. See
269+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
270+ * specification.
271+ *
272+ * The rule “Child Values Overlapping Framing Offsets” from the specification
273+ * says that the first `ay` must be decoded as `[0x01]` even though it
274+ * overlaps the first byte of the offset table. However, since commit
275+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
276+ * this as it’s exploitable. So the first `ay` must be given a default value.
277+ *
278+ * The second and third `ay`s must be given default values because of rule
279+ * “End Boundary Precedes Start Boundary”.
280+ *
281+ * The `i` must be given a default value because of rule “Start or End
282+ * Boundary of a Child Falls Outside the Container”.
283+ */
284+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
285+ const guint8 data[] = {
286+ 0x01, 0x00, 0x02,
287+ /*
288+ ^──┘
289+
290+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
291+ 2nd ay, bytes 2-0
292+ i, bytes 0-4
293+ 3rd ay, bytes 4-1
294+ ^^^^^^^^^^ Framing offsets
295+ */
296+ };
297+ gsize size = sizeof (data);
298+ GVariant *variant = NULL;
299+ GVariant *normal_variant = NULL;
300+ GVariant *expected = NULL;
301+
302+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
303+ g_assert_nonnull (variant);
304+
305+ g_assert_false (g_variant_is_normal_form (variant));
306+
307+ normal_variant = g_variant_get_normal_form (variant);
308+ g_assert_nonnull (normal_variant);
309+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
310+
311+ expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
312+ g_assert_cmpvariant (expected, variant);
313+ g_assert_cmpvariant (expected, normal_variant);
314+
315+ g_variant_unref (expected);
316+ g_variant_unref (normal_variant);
317+ g_variant_unref (variant);
318+}
319+
320+/* This is a regression test that overlapping entries in the offset table are
321+ * decoded consistently, even though they’re non-normal.
322+ *
323+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
324+static void
325+test_normal_checking_tuple_offsets4 (void)
326+{
327+ /* The expected decoding of this non-normal byte stream is complex. See
328+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
329+ * specification.
330+ *
331+ * The rule “Child Values Overlapping Framing Offsets” from the specification
332+ * says that the first `ay` must be decoded as `[0x01]` even though it
333+ * overlaps the first byte of the offset table. However, since commit
334+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
335+ * this as it’s exploitable. So the first `ay` must be given a default value.
336+ *
337+ * The second `ay` must be given a default value because of rule “End Boundary
338+ * Precedes Start Boundary”.
339+ *
340+ * The third `ay` must be given a default value because its framing offsets
341+ * overlap that of the first `ay`.
342+ */
343+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
344+ const guint8 data[] = {
345+ 0x01, 0x00, 0x02,
346+ /*
347+ ^──┘
348+
349+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
350+ 2nd ay, bytes 2-0
351+ 3rd ay, bytes 0-1
352+ ^^^^^^^^^^ Framing offsets
353+ */
354+ };
355+ gsize size = sizeof (data);
356+ GVariant *variant = NULL;
357+ GVariant *normal_variant = NULL;
358+ GVariant *expected = NULL;
359+
360+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
361+ g_assert_nonnull (variant);
362+
363+ g_assert_false (g_variant_is_normal_form (variant));
364+
365+ normal_variant = g_variant_get_normal_form (variant);
366+ g_assert_nonnull (normal_variant);
367+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
368+
369+ expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
370+ g_assert_cmpvariant (expected, variant);
371+ g_assert_cmpvariant (expected, normal_variant);
372+
373+ g_variant_unref (expected);
374+ g_variant_unref (normal_variant);
375+ g_variant_unref (variant);
376+}
377+
378 /* Test that an empty object path is normalised successfully to the base object
379 * path, ‘/’. */
380 static void
381@@ -5253,6 +5428,12 @@ main (int argc, char **argv)
382 test_normal_checking_array_offsets2);
383 g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
384 test_normal_checking_tuple_offsets);
385+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
386+ test_normal_checking_tuple_offsets2);
387+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
388+ test_normal_checking_tuple_offsets3);
389+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
390+ test_normal_checking_tuple_offsets4);
391 g_test_add_func ("/gvariant/normal-checking/empty-object-path",
392 test_normal_checking_empty_object_path);
393
394--
3952.24.4
396
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch
new file mode 100644
index 0000000000..83d0205160
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0007.patch
@@ -0,0 +1,49 @@
1From e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Wed, 16 Aug 2023 03:42:47 +0000
4Subject: [PATCH] gvariant: Port g_variant_deep_copy() to count its iterations
5 directly
6
7This is equivalent to what `GVariantIter` does, but it means that
8`g_variant_deep_copy()` is making its own `g_variant_get_child_value()`
9calls.
10
11This will be useful in an upcoming commit, where those child values will
12be inspected a little more deeply.
13
14Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
15
16Helps: #2121
17
18CVE: CVE-2023-32665
19Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793]
20Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
21---
22 glib/gvariant.c | 7 +++----
23 1 file changed, 3 insertions(+), 4 deletions(-)
24
25diff --git a/glib/gvariant.c b/glib/gvariant.c
26index cdb428e..fdd36be 100644
27--- a/glib/gvariant.c
28+++ b/glib/gvariant.c
29@@ -5799,14 +5799,13 @@ g_variant_deep_copy (GVariant *value)
30 case G_VARIANT_CLASS_VARIANT:
31 {
32 GVariantBuilder builder;
33- GVariantIter iter;
34- GVariant *child;
35+ gsize i, n_children;
36
37 g_variant_builder_init (&builder, g_variant_get_type (value));
38- g_variant_iter_init (&iter, value);
39
40- while ((child = g_variant_iter_next_value (&iter)))
41+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
42 {
43+ GVariant *child = g_variant_get_child_value (value, i);
44 g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
45 g_variant_unref (child);
46 }
47--
482.24.4
49
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
new file mode 100644
index 0000000000..f098548618
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
@@ -0,0 +1,394 @@
1From d1a293c4e29880b8d17bb826c9a426a440ca4a91 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 01:30:38 +0000
4Subject: [PATCH] gvariant: Track checked and ordered offsets independently
5
6The past few commits introduced the concept of known-good offsets in the
7offset table (which is used for variable-width arrays and tuples).
8Good offsets are ones which are non-overlapping with all the previous
9offsets in the table.
10
11If a bad offset is encountered when indexing into the array or tuple,
12the cached known-good offset index will not be increased. In this way,
13all child variants at and beyond the first bad offset can be returned as
14default values rather than dereferencing potentially invalid data.
15
16In this case, there was no information about the fact that the indexes
17between the highest known-good index and the requested one had been
18checked already. That could lead to a pathological case where an offset
19table with an invalid first offset is repeatedly checked in full when
20trying to access higher-indexed children.
21
22Avoid that by storing the index of the highest checked offset in the
23table, as well as the index of the highest good/ordered offset.
24
25Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
26
27Helps: #2121
28
29CVE: CVE-2023-32665
30Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/d1a293c4e29880b8d17bb826c9a426a440ca4a91]
31Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
32---
33 glib/gvariant-core.c | 28 ++++++++++++++++++++++++
34 glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++-----------
35 glib/gvariant-serialiser.h | 9 ++++++++
36 glib/gvariant.c | 1 +
37 glib/tests/gvariant.c | 5 +++++
38 5 files changed, 75 insertions(+), 12 deletions(-)
39
40diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
41index b951cd9..1b9d5cc 100644
42--- a/glib/gvariant-core.c
43+++ b/glib/gvariant-core.c
44@@ -67,6 +67,7 @@ struct _GVariant
45 GBytes *bytes;
46 gconstpointer data;
47 gsize ordered_offsets_up_to;
48+ gsize checked_offsets_up_to;
49 } serialised;
50
51 struct
52@@ -182,6 +183,24 @@ struct _GVariant
53 * This field is only relevant for arrays of non
54 * fixed width types and for tuples.
55 *
56+ * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores
57+ * the index of the highest element, n, whose frame
58+ * offsets (and all the preceding frame offsets)
59+ * have been checked for validity.
60+ *
61+ * It is always the case that
62+ * .checked_offsets_up_to ≥ .ordered_offsets_up_to.
63+ *
64+ * If .checked_offsets_up_to == .ordered_offsets_up_to,
65+ * then a bad offset has not been found so far.
66+ *
67+ * If .checked_offsets_up_to > .ordered_offsets_up_to,
68+ * then a bad offset has been found at
69+ * (.ordered_offsets_up_to + 1).
70+ *
71+ * This field is only relevant for arrays of non
72+ * fixed width types and for tuples.
73+ *
74 * .tree: Only valid when the instance is in tree form.
75 *
76 * Note that accesses from other threads could result in
77@@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value)
78 value->size,
79 value->depth,
80 value->contents.serialised.ordered_offsets_up_to,
81+ value->contents.serialised.checked_offsets_up_to,
82 };
83 return serialised;
84 }
85@@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value,
86 serialised.data = data;
87 serialised.depth = value->depth;
88 serialised.ordered_offsets_up_to = 0;
89+ serialised.checked_offsets_up_to = 0;
90
91 children = (gpointer *) value->contents.tree.children;
92 n_children = value->contents.tree.n_children;
93@@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
94 if (value->state & STATE_SERIALISED)
95 {
96 serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
97+ serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to;
98 }
99 else
100 {
101 serialised->ordered_offsets_up_to = 0;
102+ serialised->checked_offsets_up_to = 0;
103 }
104
105 if (serialised->data)
106@@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *value)
107 value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
108 value->contents.serialised.bytes = bytes;
109 value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
110+ value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
111 value->state |= STATE_SERIALISED;
112 }
113 }
114@@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariantType *type,
115 serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
116 serialised.depth = 0;
117 serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
118+ serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
119
120 if (!g_variant_serialised_check (serialised))
121 {
122@@ -644,6 +669,7 @@ g_variant_new_from_bytes (const GVariantType *type,
123 }
124
125 value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
126+ value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
127
128 g_clear_pointer (&owned_bytes, g_bytes_unref);
129
130@@ -1120,6 +1146,7 @@ g_variant_get_child_value (GVariant *value,
131
132 /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
133 value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
134+ value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to);
135
136 /* Check whether this would cause nesting too deep. If so, return a fake
137 * child. The only situation we expect this to happen in is with a variant,
138@@ -1147,6 +1174,7 @@ g_variant_get_child_value (GVariant *value,
139 g_bytes_ref (value->contents.serialised.bytes);
140 child->contents.serialised.data = s_child.data;
141 child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
142+ child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
143
144 return child;
145 }
146diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
147index cd4a3e6..0bf7243 100644
148--- a/glib/gvariant-serialiser.c
149+++ b/glib/gvariant-serialiser.c
150@@ -120,6 +120,8 @@
151 *
152 * @depth has no restrictions; the depth of a top-level serialised #GVariant is
153 * zero, and it increases for each level of nested child.
154+ *
155+ * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to
156 */
157
158 /* < private >
159@@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSerialised serialised)
160 !(serialised.size == 0 || serialised.data != NULL))
161 return FALSE;
162
163+ if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to)
164+ return FALSE;
165+
166 /* Depending on the native alignment requirements of the machine, the
167 * compiler will insert either 3 or 7 padding bytes after the char.
168 * This will result in the sizeof() the struct being 12 or 16.
169@@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
170 g_variant_type_info_ref (value.type_info);
171 value.depth++;
172 value.ordered_offsets_up_to = 0;
173+ value.checked_offsets_up_to = 0;
174
175 return value;
176 }
177@@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
178 {
179 if (n_children)
180 {
181- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
182+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 };
183
184 gvs_filler (&child, children[0]);
185 }
186@@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
187 value.type_info = g_variant_type_info_element (value.type_info);
188 value.depth++;
189 value.ordered_offsets_up_to = 0;
190+ value.checked_offsets_up_to = 0;
191
192 return g_variant_serialised_is_normal (value);
193 }
194@@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
195
196 value.depth++;
197 value.ordered_offsets_up_to = 0;
198+ value.checked_offsets_up_to = 0;
199
200 return value;
201 }
202@@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
203 {
204 if (n_children)
205 {
206- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
207+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 };
208
209 /* write the data for the child. */
210 gvs_filler (&child, children[0]);
211@@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
212 value.size--;
213 value.depth++;
214 value.ordered_offsets_up_to = 0;
215+ value.checked_offsets_up_to = 0;
216
217 return g_variant_serialised_is_normal (value);
218 }
219@@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
220
221 /* If the requested @index_ is beyond the set of indices whose framing offsets
222 * have been checked, check the remaining offsets to see whether they’re
223- * normal (in order, no overlapping array elements). */
224- if (index_ > value.ordered_offsets_up_to)
225+ * normal (in order, no overlapping array elements).
226+ *
227+ * Don’t bother checking if the highest known-good offset is lower than the
228+ * highest checked offset, as that means there’s an invalid element at that
229+ * index, so there’s no need to check further. */
230+ if (index_ > value.checked_offsets_up_to &&
231+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
232 {
233 switch (offsets.offset_size)
234 {
235 case 1:
236 {
237 value.ordered_offsets_up_to = find_unordered_guint8 (
238- offsets.array, value.ordered_offsets_up_to, index_ + 1);
239+ offsets.array, value.checked_offsets_up_to, index_ + 1);
240 break;
241 }
242 case 2:
243 {
244 value.ordered_offsets_up_to = find_unordered_guint16 (
245- offsets.array, value.ordered_offsets_up_to, index_ + 1);
246+ offsets.array, value.checked_offsets_up_to, index_ + 1);
247 break;
248 }
249 case 4:
250 {
251 value.ordered_offsets_up_to = find_unordered_guint32 (
252- offsets.array, value.ordered_offsets_up_to, index_ + 1);
253+ offsets.array, value.checked_offsets_up_to, index_ + 1);
254 break;
255 }
256 case 8:
257 {
258 value.ordered_offsets_up_to = find_unordered_guint64 (
259- offsets.array, value.ordered_offsets_up_to, index_ + 1);
260+ offsets.array, value.checked_offsets_up_to, index_ + 1);
261 break;
262 }
263 default:
264 /* gvs_get_offset_size() only returns maximum 8 */
265 g_assert_not_reached ();
266 }
267+
268+ value.checked_offsets_up_to = index_;
269 }
270
271 if (index_ > value.ordered_offsets_up_to)
272@@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
273
274 /* All offsets have now been checked. */
275 value.ordered_offsets_up_to = G_MAXSIZE;
276+ value.checked_offsets_up_to = G_MAXSIZE;
277
278 return TRUE;
279 }
280@@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised value,
281 * all the tuple *elements* here, not just all the framing offsets, since
282 * tuples contain a mix of elements which use framing offsets and ones which
283 * don’t. None of them are allowed to overlap. */
284- if (index_ > value.ordered_offsets_up_to)
285+ if (index_ > value.checked_offsets_up_to &&
286+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
287 {
288 gsize i, prev_i_end = 0;
289
290- if (value.ordered_offsets_up_to > 0)
291- gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
292+ if (value.checked_offsets_up_to > 0)
293+ gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
294
295- for (i = value.ordered_offsets_up_to; i <= index_; i++)
296+ for (i = value.checked_offsets_up_to; i <= index_; i++)
297 {
298 gsize i_start, i_end;
299
300@@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised value,
301 }
302
303 value.ordered_offsets_up_to = i - 1;
304+ value.checked_offsets_up_to = index_;
305 }
306
307 if (index_ > value.ordered_offsets_up_to)
308@@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
309
310 /* All element bounds have been checked above. */
311 value.ordered_offsets_up_to = G_MAXSIZE;
312+ value.checked_offsets_up_to = G_MAXSIZE;
313
314 {
315 gsize fixed_size;
316diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
317index 144aec8..e132451 100644
318--- a/glib/gvariant-serialiser.h
319+++ b/glib/gvariant-serialiser.h
320@@ -40,6 +40,15 @@ typedef struct
321 * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
322 * rather than an index into the frame offsets. */
323 gsize ordered_offsets_up_to;
324+
325+ /* Similar to @ordered_offsets_up_to. This gives the index of the child element
326+ * whose frame offset is the highest in the offset table which has been
327+ * checked so far.
328+ *
329+ * This is always ≥ @ordered_offsets_up_to. It is always an element index.
330+ *
331+ * See documentation in gvariant-core.c for `struct GVariant` for details. */
332+ gsize checked_offsets_up_to;
333 } GVariantSerialised;
334
335 /* deserialisation */
336diff --git a/glib/gvariant.c b/glib/gvariant.c
337index fdd36be..f910bd4 100644
338--- a/glib/gvariant.c
339+++ b/glib/gvariant.c
340@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
341 serialised.size = g_variant_get_size (trusted);
342 serialised.data = g_malloc (serialised.size);
343 serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
344+ serialised.checked_offsets_up_to = G_MAXSIZE;
345 g_variant_store (trusted, serialised.data);
346 g_variant_unref (trusted);
347
348diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
349index a84b02e..640f3c0 100644
350--- a/glib/tests/gvariant.c
351+++ b/glib/tests/gvariant.c
352@@ -1286,6 +1286,7 @@ random_instance_filler (GVariantSerialised *serialised,
353
354 serialised->depth = 0;
355 serialised->ordered_offsets_up_to = 0;
356+ serialised->checked_offsets_up_to = 0;
357
358 g_assert_true (serialised->type_info == instance->type_info);
359 g_assert_cmpuint (serialised->size, ==, instance->size);
360@@ -1453,6 +1454,7 @@ test_maybe (void)
361 serialised.size = needed_size;
362 serialised.depth = 0;
363 serialised.ordered_offsets_up_to = 0;
364+ serialised.checked_offsets_up_to = 0;
365
366 g_variant_serialiser_serialise (serialised,
367 random_instance_filler,
368@@ -1577,6 +1579,7 @@ test_array (void)
369 serialised.size = needed_size;
370 serialised.depth = 0;
371 serialised.ordered_offsets_up_to = 0;
372+ serialised.checked_offsets_up_to = 0;
373
374 g_variant_serialiser_serialise (serialised, random_instance_filler,
375 (gpointer *) instances, n_children);
376@@ -1742,6 +1745,7 @@ test_tuple (void)
377 serialised.size = needed_size;
378 serialised.depth = 0;
379 serialised.ordered_offsets_up_to = 0;
380+ serialised.checked_offsets_up_to = 0;
381
382 g_variant_serialiser_serialise (serialised, random_instance_filler,
383 (gpointer *) instances, n_children);
384@@ -1839,6 +1843,7 @@ test_variant (void)
385 serialised.size = needed_size;
386 serialised.depth = 0;
387 serialised.ordered_offsets_up_to = 0;
388+ serialised.checked_offsets_up_to = 0;
389
390 g_variant_serialiser_serialise (serialised, random_instance_filler,
391 (gpointer *) &instance, 1);
392--
3932.24.4
394
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch
new file mode 100644
index 0000000000..a523e60b91
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0009.patch
@@ -0,0 +1,97 @@
1From 298a537d5f6783e55d87e40011ee3fd3b22b72f9 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@endlessos.org>
3Date: Thu, 17 Aug 2023 01:39:01 +0000
4Subject: [PATCH] gvariant: Zero-initialise various GVariantSerialised objects
5
6The following few commits will add a couple of new fields to
7`GVariantSerialised`, and they should be zero-filled by default.
8
9Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
10default in a few places.
11
12Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
13
14Helps: #2121
15
16CVE: CVE-2023-32665
17Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/298a537d5f6783e55d87e40011ee3fd3b22b72f9]
18Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
19---
20 glib/gvariant.c | 2 +-
21 glib/tests/gvariant.c | 12 ++++++------
22 2 files changed, 7 insertions(+), 7 deletions(-)
23
24diff --git a/glib/gvariant.c b/glib/gvariant.c
25index f910bd4..8ba701e 100644
26--- a/glib/gvariant.c
27+++ b/glib/gvariant.c
28@@ -5936,7 +5936,7 @@ g_variant_byteswap (GVariant *value)
29 if (alignment)
30 /* (potentially) contains multi-byte numeric data */
31 {
32- GVariantSerialised serialised;
33+ GVariantSerialised serialised = { 0, };
34 GVariant *trusted;
35 GBytes *bytes;
36
37diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
38index 640f3c0..d640c81 100644
39--- a/glib/tests/gvariant.c
40+++ b/glib/tests/gvariant.c
41@@ -1446,7 +1446,7 @@ test_maybe (void)
42
43 for (flavour = 0; flavour < 8; flavour += alignment)
44 {
45- GVariantSerialised serialised;
46+ GVariantSerialised serialised = { 0, };
47 GVariantSerialised child;
48
49 serialised.type_info = type_info;
50@@ -1572,7 +1572,7 @@ test_array (void)
51
52 for (flavour = 0; flavour < 8; flavour += alignment)
53 {
54- GVariantSerialised serialised;
55+ GVariantSerialised serialised = { 0, };
56
57 serialised.type_info = array_info;
58 serialised.data = flavoured_malloc (needed_size, flavour);
59@@ -1738,7 +1738,7 @@ test_tuple (void)
60
61 for (flavour = 0; flavour < 8; flavour += alignment)
62 {
63- GVariantSerialised serialised;
64+ GVariantSerialised serialised = { 0, };
65
66 serialised.type_info = type_info;
67 serialised.data = flavoured_malloc (needed_size, flavour);
68@@ -1835,7 +1835,7 @@ test_variant (void)
69
70 for (flavour = 0; flavour < 8; flavour += alignment)
71 {
72- GVariantSerialised serialised;
73+ GVariantSerialised serialised = { 0, };
74 GVariantSerialised child;
75
76 serialised.type_info = type_info;
77@@ -2284,7 +2284,7 @@ serialise_tree (TreeInstance *tree,
78 static void
79 test_byteswap (void)
80 {
81- GVariantSerialised one, two;
82+ GVariantSerialised one = { 0, }, two = { 0, };
83 TreeInstance *tree;
84
85 tree = tree_instance_new (NULL, 3);
86@@ -2358,7 +2358,7 @@ test_serialiser_children (void)
87 static void
88 test_fuzz (gdouble *fuzziness)
89 {
90- GVariantSerialised serialised;
91+ GVariantSerialised serialised = { 0, };
92 TreeInstance *tree;
93
94 /* make an instance */
95--
962.24.4
97
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
index 1a006b9f38..60a6b843c1 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.62.6.bb
@@ -18,6 +18,44 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
18 file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ 18 file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \
19 file://tzdata-update.patch \ 19 file://tzdata-update.patch \
20 file://CVE-2020-35457.patch \ 20 file://CVE-2020-35457.patch \
21 file://CVE-2021-27218.patch \
22 file://CVE-2021-27219-01.patch \
23 file://CVE-2021-27219-02.patch \
24 file://CVE-2021-27219-03.patch \
25 file://CVE-2021-27219-04.patch \
26 file://CVE-2021-27219-05.patch \
27 file://CVE-2021-27219-06.patch \
28 file://CVE-2021-27219-07.patch \
29 file://CVE-2021-27219-08.patch \
30 file://CVE-2021-27219-09.patch \
31 file://CVE-2021-27219-10.patch \
32 file://CVE-2021-27219-11.patch \
33 file://CVE-2021-27219-reg1-1.patch \
34 file://CVE-2021-27219-reg1-2.patch \
35 file://CVE-2021-27219-reg1-4.patch \
36 file://CVE-2021-27219-reg1-5.patch \
37 file://CVE-2021-27219-reg2-1.patch \
38 file://CVE-2021-27219-reg2-2.patch \
39 file://CVE-2021-27219-reg2-3.patch \
40 file://CVE-2021-28153-1.patch \
41 file://CVE-2021-28153-2.patch \
42 file://CVE-2021-28153-3.patch \
43 file://CVE-2021-28153-4.patch \
44 file://CVE-2021-28153-5.patch \
45 file://CVE-2023-32665-0001.patch \
46 file://CVE-2023-32665-0002.patch \
47 file://CVE-2023-32665-0003.patch \
48 file://CVE-2023-32665-0004.patch \
49 file://CVE-2023-32665-0005.patch \
50 file://CVE-2023-32665-0006.patch \
51 file://CVE-2023-32665-0007.patch \
52 file://CVE-2023-32665-0008.patch \
53 file://CVE-2023-32665-0009.patch \
54 file://CVE-2023-29499.patch \
55 file://CVE-2023-32611-0001.patch \
56 file://CVE-2023-32611-0002.patch \
57 file://CVE-2023-32643.patch \
58 file://CVE-2023-32636.patch \
21 " 59 "
22 60
23SRC_URI_append_class-native = " file://relocate-modules.patch" 61SRC_URI_append_class-native = " file://relocate-modules.patch"
diff --git a/meta/recipes-core/glib-2.0/glib.inc b/meta/recipes-core/glib-2.0/glib.inc
index c3ddf18387..1849a6e05c 100644
--- a/meta/recipes-core/glib-2.0/glib.inc
+++ b/meta/recipes-core/glib-2.0/glib.inc
@@ -4,7 +4,7 @@ HOMEPAGE = "https://developer.gnome.org/glib/"
4 4
5# pcre is under BSD; 5# pcre is under BSD;
6# docs/reference/COPYING is with a 'public domain'-like license! 6# docs/reference/COPYING is with a 'public domain'-like license!
7LICENSE = "LGPLv2.1+ & BSD & PD" 7LICENSE = "LGPLv2.1+ & BSD-3-Clause & PD"
8LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \ 8LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \
9 file://glib/glib.h;beginline=4;endline=17;md5=b88abb7f3ad09607e71cb9d530155906 \ 9 file://glib/glib.h;beginline=4;endline=17;md5=b88abb7f3ad09607e71cb9d530155906 \
10 file://gmodule/COPYING;md5=4fbd65380cdd255951079008b364516c \ 10 file://gmodule/COPYING;md5=4fbd65380cdd255951079008b364516c \
diff --git a/meta/recipes-core/glibc/cross-localedef-native_2.31.bb b/meta/recipes-core/glibc/cross-localedef-native_2.31.bb
index 24de55d929..9aa24eccfe 100644
--- a/meta/recipes-core/glibc/cross-localedef-native_2.31.bb
+++ b/meta/recipes-core/glibc/cross-localedef-native_2.31.bb
@@ -20,7 +20,7 @@ inherit autotools
20FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:" 20FILESEXTRAPATHS =. "${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/glibc:"
21 21
22SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \ 22SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
23 git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef \ 23 git://github.com/kraj/localedef;branch=master;name=localedef;destsuffix=git/localedef;protocol=https \
24 \ 24 \
25 file://0001-localedef-Add-hardlink-resolver-to-build.patch;patchdir=localedef \ 25 file://0001-localedef-Add-hardlink-resolver-to-build.patch;patchdir=localedef \
26 \ 26 \
diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc
index 5f726537ff..95e2bba301 100644
--- a/meta/recipes-core/glibc/glibc-version.inc
+++ b/meta/recipes-core/glibc/glibc-version.inc
@@ -1,6 +1,6 @@
1SRCBRANCH ?= "release/2.31/master" 1SRCBRANCH ?= "release/2.31/master"
2PV = "2.31+git${SRCPV}" 2PV = "2.31+git${SRCPV}"
3SRCREV_glibc ?= "df31c7ca927242d5d4eee97f93a01e23ff47e332" 3SRCREV_glibc ?= "2d4f26e5cfda682f9ce61444b81533b83f6381af"
4SRCREV_localedef ?= "cd9f958c4c94a638fa7b2b4e21627364f1a1a655" 4SRCREV_localedef ?= "cd9f958c4c94a638fa7b2b4e21627364f1a1a655"
5 5
6GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" 6GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
diff --git a/meta/recipes-core/glibc/glibc.inc b/meta/recipes-core/glibc/glibc.inc
index 23a6ca99ae..e42040f3dc 100644
--- a/meta/recipes-core/glibc/glibc.inc
+++ b/meta/recipes-core/glibc/glibc.inc
@@ -1,7 +1,9 @@
1require glibc-common.inc 1require glibc-common.inc
2require glibc-ld.inc 2require glibc-ld.inc
3 3
4DEPENDS = "virtual/${TARGET_PREFIX}gcc libgcc-initial linux-libc-headers" 4DEPENDS = "virtual/${TARGET_PREFIX}gcc virtual/${TARGET_PREFIX}binutils${BUSUFFIX} libgcc-initial linux-libc-headers"
5BUSUFFIX= ""
6BUSUFFIX:class-nativesdk = "-crosssdk"
5 7
6PROVIDES = "virtual/libc" 8PROVIDES = "virtual/libc"
7PROVIDES += "virtual/libintl virtual/libiconv" 9PROVIDES += "virtual/libintl virtual/libiconv"
diff --git a/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch b/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch
new file mode 100644
index 0000000000..dba491f4dc
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch
@@ -0,0 +1,66 @@
1From c0669ae1a629e16b536bf11cdd0865e0dbcf4bee Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Wed, 30 Dec 2020 21:52:38 +0000
4Subject: [PATCH] elf: Refactor _dl_update_slotinfo to avoid use after free
5
6map is not valid to access here because it can be freed by a concurrent
7dlclose: during tls access (via __tls_get_addr) _dl_update_slotinfo is
8called without holding dlopen locks. So don't check the modid of map.
9
10The map == 0 and map != 0 code paths can be shared (avoiding the dtv
11resize in case of map == 0 is just an optimization: larger dtv than
12necessary would be fine too).
13
14Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
15---
16 elf/dl-tls.c | 21 +++++----------------
17 1 file changed, 5 insertions(+), 16 deletions(-)
18---
19Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=c0669ae1a629e16b536bf11cdd0865e0dbcf4bee]
20Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
21Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
22---
23diff --git a/elf/dl-tls.c b/elf/dl-tls.c
24index 24d00c14ef..f8b32b3ecb 100644
25--- a/elf/dl-tls.c
26+++ b/elf/dl-tls.c
27@@ -743,6 +743,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
28 {
29 for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
30 {
31+ size_t modid = total + cnt;
32+
33 size_t gen = listp->slotinfo[cnt].gen;
34
35 if (gen > new_gen)
36@@ -758,25 +760,12 @@ _dl_update_slotinfo (unsigned long int req_modid)
37
38 /* If there is no map this means the entry is empty. */
39 struct link_map *map = listp->slotinfo[cnt].map;
40- if (map == NULL)
41- {
42- if (dtv[-1].counter >= total + cnt)
43- {
44- /* If this modid was used at some point the memory
45- might still be allocated. */
46- free (dtv[total + cnt].pointer.to_free);
47- dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
48- dtv[total + cnt].pointer.to_free = NULL;
49- }
50-
51- continue;
52- }
53-
54 /* Check whether the current dtv array is large enough. */
55- size_t modid = map->l_tls_modid;
56- assert (total + cnt == modid);
57 if (dtv[-1].counter < modid)
58 {
59+ if (map == NULL)
60+ continue;
61+
62 /* Resize the dtv. */
63 dtv = _dl_resize_dtv (dtv);
64
65--
662.27.0
diff --git a/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch
new file mode 100644
index 0000000000..25beee1d50
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch
@@ -0,0 +1,191 @@
1From 1387ad6225c2222f027790e3f460e31aa5dd2c54 Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Wed, 30 Dec 2020 19:19:37 +0000
4Subject: [PATCH] elf: Fix data races in pthread_create and TLS access [BZ
5 #19329]
6
7DTV setup at thread creation (_dl_allocate_tls_init) is changed
8to take the dlopen lock, GL(dl_load_lock). Avoiding data races
9here without locks would require design changes: the map that is
10accessed for static TLS initialization here may be concurrently
11freed by dlclose. That use after free may be solved by only
12locking around static TLS setup or by ensuring dlclose does not
13free modules with static TLS, however currently every link map
14with TLS has to be accessed at least to see if it needs static
15TLS. And even if that's solved, still a lot of atomics would be
16needed to synchronize DTV related globals without a lock. So fix
17both bug 19329 and bug 27111 with a lock that prevents DTV setup
18running concurrently with dlopen or dlclose.
19
20_dl_update_slotinfo at TLS access still does not use any locks
21so CONCURRENCY NOTES are added to explain the synchronization.
22The early exit from the slotinfo walk when max_modid is reached
23is not strictly necessary, but does not hurt either.
24
25An incorrect acquire load was removed from _dl_resize_dtv: it
26did not synchronize with any release store or fence and
27synchronization is now handled separately at thread creation
28and TLS access time.
29
30There are still a number of racy read accesses to globals that
31will be changed to relaxed MO atomics in a followup patch. This
32should not introduce regressions compared to existing behaviour
33and avoid cluttering the main part of the fix.
34
35Not all TLS access related data races got fixed here: there are
36additional races at lazy tlsdesc relocations see bug 27137.
37
38Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
39---
40 elf/dl-tls.c | 63 +++++++++++++++++++++++++++++++++++++++-------------
41 1 file changed, 47 insertions(+), 16 deletions(-)
42---
43Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=1387ad6225c2222f027790e3f460e31aa5dd2c54]
44Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
45Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
46---
47diff --git a/elf/dl-tls.c b/elf/dl-tls.c
48index 6baff0c1ea..94f3cdbae0 100644
49--- a/elf/dl-tls.c
50+++ b/elf/dl-tls.c
51@@ -475,14 +475,11 @@ extern dtv_t _dl_static_dtv[];
52 #endif
53
54 static dtv_t *
55-_dl_resize_dtv (dtv_t *dtv)
56+_dl_resize_dtv (dtv_t *dtv, size_t max_modid)
57 {
58 /* Resize the dtv. */
59 dtv_t *newp;
60- /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
61- other threads concurrently. */
62- size_t newsize
63- = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS;
64+ size_t newsize = max_modid + DTV_SURPLUS;
65 size_t oldsize = dtv[-1].counter;
66
67 if (dtv == GL(dl_initial_dtv))
68@@ -528,11 +525,14 @@ _dl_allocate_tls_init (void *result)
69 size_t total = 0;
70 size_t maxgen = 0;
71
72+ /* Protects global dynamic TLS related state. */
73+ __rtld_lock_lock_recursive (GL(dl_load_lock));
74+
75 /* Check if the current dtv is big enough. */
76 if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
77 {
78 /* Resize the dtv. */
79- dtv = _dl_resize_dtv (dtv);
80+ dtv = _dl_resize_dtv (dtv, GL(dl_tls_max_dtv_idx));
81
82 /* Install this new dtv in the thread data structures. */
83 INSTALL_DTV (result, &dtv[-1]);
84@@ -600,6 +600,7 @@ _dl_allocate_tls_init (void *result)
85 listp = listp->next;
86 assert (listp != NULL);
87 }
88+ __rtld_lock_unlock_recursive (GL(dl_load_lock));
89
90 /* The DTV version is up-to-date now. */
91 dtv[0].counter = maxgen;
92@@ -734,12 +735,29 @@ _dl_update_slotinfo (unsigned long int req_modid)
93
94 if (dtv[0].counter < listp->slotinfo[idx].gen)
95 {
96- /* The generation counter for the slot is higher than what the
97- current dtv implements. We have to update the whole dtv but
98- only those entries with a generation counter <= the one for
99- the entry we need. */
100+ /* CONCURRENCY NOTES:
101+
102+ Here the dtv needs to be updated to new_gen generation count.
103+
104+ This code may be called during TLS access when GL(dl_load_lock)
105+ is not held. In that case the user code has to synchronize with
106+ dlopen and dlclose calls of relevant modules. A module m is
107+ relevant if the generation of m <= new_gen and dlclose of m is
108+ synchronized: a memory access here happens after the dlopen and
109+ before the dlclose of relevant modules. The dtv entries for
110+ relevant modules need to be updated, other entries can be
111+ arbitrary.
112+
113+ This e.g. means that the first part of the slotinfo list can be
114+ accessed race free, but the tail may be concurrently extended.
115+ Similarly relevant slotinfo entries can be read race free, but
116+ other entries are racy. However updating a non-relevant dtv
117+ entry does not affect correctness. For a relevant module m,
118+ max_modid >= modid of m. */
119 size_t new_gen = listp->slotinfo[idx].gen;
120 size_t total = 0;
121+ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
122+ assert (max_modid >= req_modid);
123
124 /* We have to look through the entire dtv slotinfo list. */
125 listp = GL(dl_tls_dtv_slotinfo_list);
126@@ -749,12 +767,14 @@ _dl_update_slotinfo (unsigned long int req_modid)
127 {
128 size_t modid = total + cnt;
129
130+ /* Later entries are not relevant. */
131+ if (modid > max_modid)
132+ break;
133+
134 size_t gen = listp->slotinfo[cnt].gen;
135
136 if (gen > new_gen)
137- /* This is a slot for a generation younger than the
138- one we are handling now. It might be incompletely
139- set up so ignore it. */
140+ /* Not relevant. */
141 continue;
142
143 /* If the entry is older than the current dtv layout we
144@@ -771,7 +791,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
145 continue;
146
147 /* Resize the dtv. */
148- dtv = _dl_resize_dtv (dtv);
149+ dtv = _dl_resize_dtv (dtv, max_modid);
150
151 assert (modid <= dtv[-1].counter);
152
153@@ -793,8 +813,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
154 }
155
156 total += listp->len;
157+ if (total > max_modid)
158+ break;
159+
160+ /* Synchronize with _dl_add_to_slotinfo. Ideally this would
161+ be consume MO since we only need to order the accesses to
162+ the next node after the read of the address and on most
163+ hardware (other than alpha) a normal load would do that
164+ because of the address dependency. */
165+ listp = atomic_load_acquire (&listp->next);
166 }
167- while ((listp = listp->next) != NULL);
168+ while (listp != NULL);
169
170 /* This will be the new maximum generation counter. */
171 dtv[0].counter = new_gen;
172@@ -986,7 +1015,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
173 the first slot. */
174 assert (idx == 0);
175
176- listp = prevp->next = (struct dtv_slotinfo_list *)
177+ listp = (struct dtv_slotinfo_list *)
178 malloc (sizeof (struct dtv_slotinfo_list)
179 + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
180 if (listp == NULL)
181@@ -1000,6 +1029,8 @@ cannot create TLS data structures"));
182 listp->next = NULL;
183 memset (listp->slotinfo, '\0',
184 TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
185+ /* Synchronize with _dl_update_slotinfo. */
186+ atomic_store_release (&prevp->next, listp);
187 }
188
189 /* Add the information into the slotinfo data structure. */
190--
1912.27.0
diff --git a/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch
new file mode 100644
index 0000000000..eb8ef3161c
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch
@@ -0,0 +1,206 @@
1From f4f8f4d4e0f92488431b268c8cd9555730b9afe9 Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Wed, 30 Dec 2020 19:19:37 +0000
4Subject: [PATCH] elf: Use relaxed atomics for racy accesses [BZ #19329]
5
6This is a follow up patch to the fix for bug 19329. This adds relaxed
7MO atomics to accesses that were previously data races but are now
8race conditions, and where relaxed MO is sufficient.
9
10The race conditions all follow the pattern that the write is behind the
11dlopen lock, but a read can happen concurrently (e.g. during tls access)
12without holding the lock. For slotinfo entries the read value only
13matters if it reads from a synchronized write in dlopen or dlclose,
14otherwise the related dtv entry is not valid to access so it is fine
15to leave it in an inconsistent state. The same applies for
16GL(dl_tls_max_dtv_idx) and GL(dl_tls_generation), but there the
17algorithm relies on the fact that the read of the last synchronized
18write is an increasing value.
19
20Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
21---
22 elf/dl-close.c | 20 +++++++++++++-------
23 elf/dl-open.c | 5 ++++-
24 elf/dl-tls.c | 31 +++++++++++++++++++++++--------
25 sysdeps/x86_64/dl-tls.c | 3 ++-
26 4 files changed, 42 insertions(+), 17 deletions(-)
27---
28Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=f4f8f4d4e0f92488431b268c8cd9555730b9afe9]
29Comment: Hunks from elf/dl-open.c and elf/dl-tls.c are refreshed due to offset change.
30Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
31Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
32---
33diff --git a/elf/dl-close.c b/elf/dl-close.c
34index c51becd06b..3720e47dd1 100644
35--- a/elf/dl-close.c
36+++ b/elf/dl-close.c
37@@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
38 {
39 assert (old_map->l_tls_modid == idx);
40
41- /* Mark the entry as unused. */
42- listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
43- listp->slotinfo[idx - disp].map = NULL;
44+ /* Mark the entry as unused. These can be read concurrently. */
45+ atomic_store_relaxed (&listp->slotinfo[idx - disp].gen,
46+ GL(dl_tls_generation) + 1);
47+ atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL);
48 }
49
50 /* If this is not the last currently used entry no need to look
51@@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
52
53 if (listp->slotinfo[idx - disp].map != NULL)
54 {
55- /* Found a new last used index. */
56- GL(dl_tls_max_dtv_idx) = idx;
57+ /* Found a new last used index. This can be read concurrently. */
58+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx);
59 return true;
60 }
61 }
62@@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force)
63 GL(dl_tls_dtv_slotinfo_list), 0,
64 imap->l_init_called))
65 /* All dynamically loaded modules with TLS are unloaded. */
66- GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
67+ /* Can be read concurrently. */
68+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx),
69+ GL(dl_tls_static_nelem));
70
71 if (imap->l_tls_offset != NO_TLS_OFFSET
72 && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET)
73@@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force)
74 /* If we removed any object which uses TLS bump the generation counter. */
75 if (any_tls)
76 {
77- if (__glibc_unlikely (++GL(dl_tls_generation) == 0))
78+ size_t newgen = GL(dl_tls_generation) + 1;
79+ if (__glibc_unlikely (newgen == 0))
80 _dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n");
81+ /* Can be read concurrently. */
82+ atomic_store_relaxed (&GL(dl_tls_generation), newgen);
83
84 if (tls_free_end == GL(dl_tls_static_used))
85 GL(dl_tls_static_used) = tls_free_start;
86diff --git a/elf/dl-open.c b/elf/dl-open.c
87index 09f0df7d38..bb79ef00f1 100644
88--- a/elf/dl-open.c
89+++ b/elf/dl-open.c
90@@ -387,9 +387,12 @@
91 }
92 }
93
94- if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
95+ size_t newgen = GL(dl_tls_generation) + 1;
96+ if (__glibc_unlikely (newgen == 0))
97 _dl_fatal_printf (N_("\
98 TLS generation counter wrapped! Please report this."));
99+ /* Can be read concurrently. */
100+ atomic_store_relaxed (&GL(dl_tls_generation), newgen);
101
102 /* We need a second pass for static tls data, because
103 _dl_update_slotinfo must not be run while calls to
104diff --git a/elf/dl-tls.c b/elf/dl-tls.c
105index 94f3cdbae0..dc69cd984e 100644
106--- a/elf/dl-tls.c
107+++ b/elf/dl-tls.c
108@@ -96,7 +96,9 @@
109 /* No gaps, allocate a new entry. */
110 nogaps:
111
112- result = ++GL(dl_tls_max_dtv_idx);
113+ result = GL(dl_tls_max_dtv_idx) + 1;
114+ /* Can be read concurrently. */
115+ atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result);
116 }
117
118 return result;
119@@ -279,10 +281,12 @@
120 dtv_t *dtv;
121 size_t dtv_length;
122
123+ /* Relaxed MO, because the dtv size is later rechecked, not relied on. */
124+ size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
125 /* We allocate a few more elements in the dtv than are needed for the
126 initial set of modules. This should avoid in most cases expansions
127 of the dtv. */
128- dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
129+ dtv_length = max_modid + DTV_SURPLUS;
130 dtv = calloc (dtv_length + 2, sizeof (dtv_t));
131 if (dtv != NULL)
132 {
133@@ -687,7 +691,7 @@
134 if (modid > max_modid)
135 break;
136
137- size_t gen = listp->slotinfo[cnt].gen;
138+ size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen);
139
140 if (gen > new_gen)
141 /* Not relevant. */
142@@ -699,7 +703,8 @@
143 continue;
144
145 /* If there is no map this means the entry is empty. */
146- struct link_map *map = listp->slotinfo[cnt].map;
147+ struct link_map *map
148+ = atomic_load_relaxed (&listp->slotinfo[cnt].map);
149 /* Check whether the current dtv array is large enough. */
150 if (dtv[-1].counter < modid)
151 {
152@@ -843,7 +848,12 @@
153 {
154 dtv_t *dtv = THREAD_DTV ();
155
156- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
157+ /* Update is needed if dtv[0].counter < the generation of the accessed
158+ module. The global generation counter is used here as it is easier
159+ to check. Synchronization for the relaxed MO access is guaranteed
160+ by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */
161+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
162+ if (__glibc_unlikely (dtv[0].counter != gen))
163 return update_get_addr (GET_ADDR_PARAM);
164
165 void *p = dtv[GET_ADDR_MODULE].pointer.val;
166@@ -866,7 +876,10 @@
167 return NULL;
168
169 dtv_t *dtv = THREAD_DTV ();
170- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
171+ /* This may be called without holding the GL(dl_load_lock). Reading
172+ arbitrary gen value is fine since this is best effort code. */
173+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
174+ if (__glibc_unlikely (dtv[0].counter != gen))
175 {
176 /* This thread's DTV is not completely current,
177 but it might already cover this module. */
178@@ -961,7 +974,9 @@
179 /* Add the information into the slotinfo data structure. */
180 if (do_add)
181 {
182- listp->slotinfo[idx].map = l;
183- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
184+ /* Can be read concurrently. See _dl_update_slotinfo. */
185+ atomic_store_relaxed (&listp->slotinfo[idx].map, l);
186+ atomic_store_relaxed (&listp->slotinfo[idx].gen,
187+ GL(dl_tls_generation) + 1);
188 }
189 }
190
191diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
192index 6595f6615b..24ef560b71 100644
193--- a/sysdeps/x86_64/dl-tls.c
194+++ b/sysdeps/x86_64/dl-tls.c
195@@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
196 {
197 dtv_t *dtv = THREAD_DTV ();
198
199- if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
200+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
201+ if (__glibc_unlikely (dtv[0].counter != gen))
202 return update_get_addr (GET_ADDR_PARAM);
203
204 return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
205--
2062.27.0
diff --git a/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch b/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch
new file mode 100644
index 0000000000..f22e52ea99
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0033-elf-Add-test-case-for-BZ-19329.patch
@@ -0,0 +1,144 @@
1From 9d0e30329c23b5ad736fda3f174208c25970dbce Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Tue, 13 Dec 2016 12:28:41 +0000
4Subject: [PATCH] elf: Add test case for [BZ #19329]
5
6Test concurrent dlopen and pthread_create when the loaded modules have
7TLS. This triggers dl-tls assertion failures more reliably than the
8nptl/tst-stack4 test.
9
10The dlopened module has 100 DT_NEEDED dependencies with TLS, they were
11reused from an existing TLS test. The number of created threads during
12dlopen depends on filesystem speed and hardware, but at most 3 threads
13are alive at a time to limit resource usage.
14
15Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
16---
17 elf/Makefile | 9 ++++--
18 elf/tst-tls21.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
19 elf/tst-tls21mod.c | 1 +
20 3 files changed, 76 insertions(+), 2 deletions(-)
21 create mode 100644 elf/tst-tls21.c
22 create mode 100644 elf/tst-tls21mod.c
23---
24Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=9d0e30329c23b5ad736fda3f174208c25970dbce]
25Comment: Hunks from elf/Makefile are refreshed as per glibc 2.31 codebase.
26Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
27Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
28---
29diff --git a/elf/Makefile b/elf/Makefile
30index d3e909637a..3241cb6046 100644
31--- a/elf/Makefile
32+++ b/elf/Makefile
33@@ -201,7 +201,7 @@
34 tst-unwind-ctor tst-unwind-main tst-audit13 \
35 tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \
36 tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \
37- tst-dlopenfail-2
38+ tst-dlopenfail-2 tst-tls21
39 # reldep9
40 tests-internal += loadtest unload unload2 circleload1 \
41 neededtest neededtest2 neededtest3 neededtest4 \
42@@ -312,7 +312,7 @@
43 tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \
44 tst-initlazyfailmod tst-finilazyfailmod \
45 tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
46- tst-dlopenfailmod3 tst-ldconfig-ld-mod
47+ tst-dlopenfailmod3 tst-ldconfig-ld-mod tst-tls21mod
48 # Most modules build with _ISOMAC defined, but those filtered out
49 # depend on internal headers.
50 modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
51@@ -1697,5 +1697,10 @@
52 $(objpfx)tst-dlopen-nodelete-reloc-mod16.so
53 LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed
54
55+# Reuses tst-tls-many-dynamic-modules
56+$(objpfx)tst-tls21: $(libdl) $(shared-thread-library)
57+$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so
58+$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
59+
60 $(objpfx)tst-ldconfig-ld_so_conf-update.out: $(objpfx)tst-ldconfig-ld-mod.so
61 $(objpfx)tst-ldconfig-ld_so_conf-update: $(libdl)
62diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c
63new file mode 100644
64index 0000000000..560bf5813a
65--- /dev/null
66+++ b/elf/tst-tls21.c
67@@ -0,0 +1,68 @@
68+/* Test concurrent dlopen and pthread_create: BZ 19329.
69+ Copyright (C) 2021 Free Software Foundation, Inc.
70+ This file is part of the GNU C Library.
71+
72+ The GNU C Library is free software; you can redistribute it and/or
73+ modify it under the terms of the GNU Lesser General Public
74+ License as published by the Free Software Foundation; either
75+ version 2.1 of the License, or (at your option) any later version.
76+
77+ The GNU C Library is distributed in the hope that it will be useful,
78+ but WITHOUT ANY WARRANTY; without even the implied warranty of
79+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
80+ Lesser General Public License for more details.
81+
82+ You should have received a copy of the GNU Lesser General Public
83+ License along with the GNU C Library; if not, see
84+ <http://www.gnu.org/licenses/>. */
85+
86+#include <dlfcn.h>
87+#include <pthread.h>
88+#include <stdio.h>
89+#include <stdatomic.h>
90+#include <support/xdlfcn.h>
91+#include <support/xthread.h>
92+
93+#define THREADS 10000
94+
95+static atomic_int done;
96+
97+static void *
98+start (void *a)
99+{
100+ /* Load a module with many dependencies that each have TLS. */
101+ xdlopen ("tst-tls21mod.so", RTLD_LAZY);
102+ atomic_store_explicit (&done, 1, memory_order_release);
103+ return 0;
104+}
105+
106+static void *
107+nop (void *a)
108+{
109+ return 0;
110+}
111+
112+static int
113+do_test (void)
114+{
115+ pthread_t t1, t2;
116+ int i;
117+
118+ /* Load a module with lots of dependencies and TLS. */
119+ t1 = xpthread_create (0, start, 0);
120+
121+ /* Concurrently create lots of threads until dlopen is observably done. */
122+ for (i = 0; i < THREADS; i++)
123+ {
124+ if (atomic_load_explicit (&done, memory_order_acquire) != 0)
125+ break;
126+ t2 = xpthread_create (0, nop, 0);
127+ xpthread_join (t2);
128+ }
129+
130+ xpthread_join (t1);
131+ printf ("threads created during dlopen: %d\n", i);
132+ return 0;
133+}
134+
135+#include <support/test-driver.c>
136diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c
137new file mode 100644
138index 0000000000..206ece4fb3
139--- /dev/null
140+++ b/elf/tst-tls21mod.c
141@@ -0,0 +1 @@
142+int __thread x;
143--
1442.27.0
diff --git a/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch b/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch
new file mode 100644
index 0000000000..a87afe3230
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch
@@ -0,0 +1,180 @@
1From ba33937be210da5d07f7f01709323743f66011ce Mon Sep 17 00:00:00 2001
2From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
3Date: Fri, 25 Jun 2021 10:54:12 -0300
4Subject: [PATCH] elf: Fix DTV gap reuse logic (BZ #27135)
5
6This is updated version of the 572bd547d57a (reverted by 40ebfd016ad2)
7that fixes the _dl_next_tls_modid issues.
8
9This issue with 572bd547d57a patch is the DTV entry will be only
10update on dl_open_worker() with the update_tls_slotinfo() call after
11all dependencies are being processed by _dl_map_object_deps(). However
12_dl_map_object_deps() itself might call _dl_next_tls_modid(), and since
13the _dl_tls_dtv_slotinfo_list::map is not yet set the entry will be
14wrongly reused.
15
16This patch fixes by renaming the _dl_next_tls_modid() function to
17_dl_assign_tls_modid() and by passing the link_map so it can set
18the slotinfo value so a subsequente _dl_next_tls_modid() call will
19see the entry as allocated.
20
21The intermediary value is cleared up on remove_slotinfo() for the case
22a library fails to load with RTLD_NOW.
23
24This patch fixes BZ #27135.
25
26Checked on x86_64-linux-gnu.
27
28Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
29---
30 elf/dl-close.c | 8 +-
31 elf/dl-load.c | 2 +-
32 elf/dl-open.c | 10 --
33 elf/dl-tls.c | 17 +--
34 elf/rtld.c | 2 +-
35 sysdeps/generic/ldsodefs.h | 4 +-
36 6 files changed, 349 insertions(+), 33 deletions(-)
37---
38Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ba33937be210da5d07f7f01709323743f66011ce]
39Comment: Removed hunks those were related to test. Hunk from elf/rtld.c is refreshed.
40Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
41Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
42---
43diff --git a/elf/dl-close.c b/elf/dl-close.c
44index 3720e47dd1..f39001cab9 100644
45--- a/elf/dl-close.c
46+++ b/elf/dl-close.c
47@@ -77,8 +77,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
48 object that wasn't fully set up. */
49 if (__glibc_likely (old_map != NULL))
50 {
51- assert (old_map->l_tls_modid == idx);
52-
53 /* Mark the entry as unused. These can be read concurrently. */
54 atomic_store_relaxed (&listp->slotinfo[idx - disp].gen,
55 GL(dl_tls_generation) + 1);
56@@ -88,7 +86,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
57 /* If this is not the last currently used entry no need to look
58 further. */
59 if (idx != GL(dl_tls_max_dtv_idx))
60- return true;
61+ {
62+ /* There is an unused dtv entry in the middle. */
63+ GL(dl_tls_dtv_gaps) = true;
64+ return true;
65+ }
66 }
67
68 while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
69diff --git a/elf/dl-load.c b/elf/dl-load.c
70index a08df001af..650e4edc35 100644
71--- a/elf/dl-load.c
72+++ b/elf/dl-load.c
73@@ -1498,7 +1498,7 @@ cannot enable executable stack as shared object requires");
74 not set up TLS data structures, so don't use them now. */
75 || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)))
76 /* Assign the next available module ID. */
77- l->l_tls_modid = _dl_next_tls_modid ();
78+ _dl_assign_tls_modid (l);
79
80 #ifdef DL_AFTER_LOAD
81 DL_AFTER_LOAD (l);
82diff --git a/elf/dl-open.c b/elf/dl-open.c
83index a066f39bd0..d2240d8747 100644
84--- a/elf/dl-open.c
85+++ b/elf/dl-open.c
86@@ -899,16 +899,6 @@ no more namespaces available for dlmopen()"));
87 state if relocation failed, for example. */
88 if (args.map)
89 {
90- /* Maybe some of the modules which were loaded use TLS.
91- Since it will be removed in the following _dl_close call
92- we have to mark the dtv array as having gaps to fill the
93- holes. This is a pessimistic assumption which won't hurt
94- if not true. There is no need to do this when we are
95- loading the auditing DSOs since TLS has not yet been set
96- up. */
97- if ((mode & __RTLD_AUDIT) == 0)
98- GL(dl_tls_dtv_gaps) = true;
99-
100 _dl_close_worker (args.map, true);
101
102 /* All l_nodelete_pending objects should have been deleted
103diff --git a/elf/dl-tls.c b/elf/dl-tls.c
104index 2b5161d10a..423e380f7c 100644
105--- a/elf/dl-tls.c
106+++ b/elf/dl-tls.c
107@@ -126,8 +126,8 @@ oom (void)
108 }
109
110
111-size_t
112-_dl_next_tls_modid (void)
113+void
114+_dl_assign_tls_modid (struct link_map *l)
115 {
116 size_t result;
117
118@@ -157,7 +157,11 @@ _dl_next_tls_modid (void)
119 }
120
121 if (result - disp < runp->len)
122- break;
123+ {
124+ /* Mark the entry as used, so any dependency see it. */
125+ atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
126+ break;
127+ }
128
129 disp += runp->len;
130 }
131@@ -184,17 +188,14 @@ _dl_next_tls_modid (void)
132 atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result);
133 }
134
135- return result;
136+ l->l_tls_modid = result;
137 }
138
139
140 size_t
141 _dl_count_modids (void)
142 {
143- /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
144- we fail to load a module and unload it leaving a gap. If we don't
145- have gaps then the number of modids is the current maximum so
146- return that. */
147+ /* The count is the max unless dlclose or failed dlopen created gaps. */
148 if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
149 return GL(dl_tls_max_dtv_idx);
150
151diff --git a/elf/rtld.c b/elf/rtld.c
152index e3fb2a5b2a..d733359eaf 100644
153--- a/elf/rtld.c
154+++ b/elf/rtld.c
155@@ -1612,7 +1612,7 @@
156 /* Add the dynamic linker to the TLS list if it also uses TLS. */
157 if (GL(dl_rtld_map).l_tls_blocksize != 0)
158 /* Assign a module ID. Do this before loading any audit modules. */
159- GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
160+ _dl_assign_tls_modid (&GL(dl_rtld_map));
161
162 /* If we have auditing DSOs to load, do it now. */
163 bool need_security_init = true;
164diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
165index 176394de4d..9c15259236 100644
166--- a/sysdeps/generic/ldsodefs.h
167+++ b/sysdeps/generic/ldsodefs.h
168@@ -1171,8 +1171,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
169 extern void _dl_sysdep_start_cleanup (void) attribute_hidden;
170
171
172-/* Determine next available module ID. */
173-extern size_t _dl_next_tls_modid (void) attribute_hidden;
174+/* Determine next available module ID and set the L l_tls_modid. */
175+extern void _dl_assign_tls_modid (struct link_map *l) attribute_hidden;
176
177 /* Count the modules with TLS segments. */
178 extern size_t _dl_count_modids (void) attribute_hidden;
179--
1802.27.0
diff --git a/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch b/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch
new file mode 100644
index 0000000000..899111b118
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch
@@ -0,0 +1,56 @@
1From 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86 Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Thu, 11 Feb 2021 11:29:23 +0000
4Subject: [PATCH] x86_64: Avoid lazy relocation of tlsdesc [BZ #27137]
5
6Lazy tlsdesc relocation is racy because the static tls optimization and
7tlsdesc management operations are done without holding the dlopen lock.
8
9This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67
10for aarch64, but it fixes a different race: bug 27137.
11
12Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to
13relocate tlsdesc lazily, but that does not work in a BIND_NOW module
14due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at
15load time fixes this bug 27721 too.
16---
17 sysdeps/x86_64/dl-machine.h | 19 ++++++++++++++-----
18 1 file changed, 14 insertions(+), 5 deletions(-)
19---
20Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86]
21Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
22Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
23---
24diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
25index 103eee6c3f..9a876a371e 100644
26--- a/sysdeps/x86_64/dl-machine.h
27+++ b/sysdeps/x86_64/dl-machine.h
28@@ -570,12 +570,21 @@ elf_machine_lazy_rel (struct link_map *map,
29 }
30 else if (__glibc_likely (r_type == R_X86_64_TLSDESC))
31 {
32- struct tlsdesc volatile * __attribute__((__unused__)) td =
33- (struct tlsdesc volatile *)reloc_addr;
34+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
35+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
36+ const ElfW (Sym) *sym = &symtab[symndx];
37+ const struct r_found_version *version = NULL;
38
39- td->arg = (void*)reloc;
40- td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
41- + map->l_addr);
42+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
43+ {
44+ const ElfW (Half) *vernum =
45+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
46+ version = &map->l_versions[vernum[symndx] & 0x7fff];
47+ }
48+
49+ /* Always initialize TLS descriptors completely at load time, in
50+ case static TLS is allocated for it that requires locking. */
51+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
52 }
53 else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE))
54 {
55--
562.27.0
diff --git a/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch b/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch
new file mode 100644
index 0000000000..ad0a1147aa
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch
@@ -0,0 +1,124 @@
1From ddcacd91cc10ff92d6201eda87047d029c14158d Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Thu, 11 Feb 2021 11:40:11 +0000
4Subject: [PATCH] i386: Avoid lazy relocation of tlsdesc [BZ #27137]
5
6Lazy tlsdesc relocation is racy because the static tls optimization and
7tlsdesc management operations are done without holding the dlopen lock.
8
9This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67
10for aarch64, but it fixes a different race: bug 27137.
11
12On i386 the code is a bit more complicated than on x86_64 because both
13rel and rela relocs are supported.
14---
15 sysdeps/i386/dl-machine.h | 76 ++++++++++++++++++---------------------
16 1 file changed, 34 insertions(+), 42 deletions(-)
17---
18Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ddcacd91cc10ff92d6201eda87047d029c14158d]
19Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
20Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
21---
22diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
23index 23e9cc3bfb..590b41d8d7 100644
24--- a/sysdeps/i386/dl-machine.h
25+++ b/sysdeps/i386/dl-machine.h
26@@ -688,50 +688,32 @@ elf_machine_lazy_rel (struct link_map *map,
27 }
28 else if (__glibc_likely (r_type == R_386_TLS_DESC))
29 {
30- struct tlsdesc volatile * __attribute__((__unused__)) td =
31- (struct tlsdesc volatile *)reloc_addr;
32-
33- /* Handle relocations that reference the local *ABS* in a simple
34- way, so as to preserve a potential addend. */
35- if (ELF32_R_SYM (reloc->r_info) == 0)
36- td->entry = _dl_tlsdesc_resolve_abs_plus_addend;
37- /* Given a known-zero addend, we can store a pointer to the
38- reloc in the arg position. */
39- else if (td->arg == 0)
40- {
41- td->arg = (void*)reloc;
42- td->entry = _dl_tlsdesc_resolve_rel;
43- }
44- else
45- {
46- /* We could handle non-*ABS* relocations with non-zero addends
47- by allocating dynamically an arg to hold a pointer to the
48- reloc, but that sounds pointless. */
49- const Elf32_Rel *const r = reloc;
50- /* The code below was borrowed from elf_dynamic_do_rel(). */
51- const ElfW(Sym) *const symtab =
52- (const void *) D_PTR (map, l_info[DT_SYMTAB]);
53+ const Elf32_Rel *const r = reloc;
54+ /* The code below was borrowed from elf_dynamic_do_rel(). */
55+ const ElfW(Sym) *const symtab =
56+ (const void *) D_PTR (map, l_info[DT_SYMTAB]);
57
58+ /* Always initialize TLS descriptors completely at load time, in
59+ case static TLS is allocated for it that requires locking. */
60 # ifdef RTLD_BOOTSTRAP
61- /* The dynamic linker always uses versioning. */
62- assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
63+ /* The dynamic linker always uses versioning. */
64+ assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
65 # else
66- if (map->l_info[VERSYMIDX (DT_VERSYM)])
67+ if (map->l_info[VERSYMIDX (DT_VERSYM)])
68 # endif
69- {
70- const ElfW(Half) *const version =
71- (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
72- ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
73- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
74- &map->l_versions[ndx],
75- (void *) (l_addr + r->r_offset), skip_ifunc);
76- }
77+ {
78+ const ElfW(Half) *const version =
79+ (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
80+ ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
81+ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
82+ &map->l_versions[ndx],
83+ (void *) (l_addr + r->r_offset), skip_ifunc);
84+ }
85 # ifndef RTLD_BOOTSTRAP
86- else
87- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
88- (void *) (l_addr + r->r_offset), skip_ifunc);
89+ else
90+ elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
91+ (void *) (l_addr + r->r_offset), skip_ifunc);
92 # endif
93- }
94 }
95 else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
96 {
97@@ -758,11 +740,21 @@ elf_machine_lazy_rela (struct link_map *map,
98 ;
99 else if (__glibc_likely (r_type == R_386_TLS_DESC))
100 {
101- struct tlsdesc volatile * __attribute__((__unused__)) td =
102- (struct tlsdesc volatile *)reloc_addr;
103+ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
104+ const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
105+ const ElfW (Sym) *sym = &symtab[symndx];
106+ const struct r_found_version *version = NULL;
107+
108+ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
109+ {
110+ const ElfW (Half) *vernum =
111+ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
112+ version = &map->l_versions[vernum[symndx] & 0x7fff];
113+ }
114
115- td->arg = (void*)reloc;
116- td->entry = _dl_tlsdesc_resolve_rela;
117+ /* Always initialize TLS descriptors completely at load time, in
118+ case static TLS is allocated for it that requires locking. */
119+ elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
120 }
121 else if (__glibc_unlikely (r_type == R_386_IRELATIVE))
122 {
123--
1242.27.0
diff --git a/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch b/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch
new file mode 100644
index 0000000000..7a10131bad
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/0037-Avoid-deadlock-between-pthread_create-and-ctors.patch
@@ -0,0 +1,276 @@
1From 83b5323261bb72313bffcf37476c1b8f0847c736 Mon Sep 17 00:00:00 2001
2From: Szabolcs Nagy <szabolcs.nagy@arm.com>
3Date: Wed, 15 Sep 2021 15:16:19 +0100
4Subject: [PATCH] elf: Avoid deadlock between pthread_create and ctors [BZ
5 #28357]
6
7The fix for bug 19329 caused a regression such that pthread_create can
8deadlock when concurrent ctors from dlopen are waiting for it to finish.
9Use a new GL(dl_load_tls_lock) in pthread_create that is not taken
10around ctors in dlopen.
11
12The new lock is also used in __tls_get_addr instead of GL(dl_load_lock).
13
14The new lock is held in _dl_open_worker and _dl_close_worker around
15most of the logic before/after the init/fini routines. When init/fini
16routines are running then TLS is in a consistent, usable state.
17In _dl_open_worker the new lock requires catching and reraising dlopen
18failures that happen in the critical section.
19
20The new lock is reinitialized in a fork child, to keep the existing
21behaviour and it is kept recursive in case malloc interposition or TLS
22access from signal handlers can retake it. It is not obvious if this
23is necessary or helps, but avoids changing the preexisting behaviour.
24
25The new lock may be more appropriate for dl_iterate_phdr too than
26GL(dl_load_write_lock), since TLS state of an incompletely loaded
27module may be accessed. If the new lock can replace the old one,
28that can be a separate change.
29
30Fixes bug 28357.
31
32Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
33---
34 elf/dl-close.c | 6 ++
35 elf/dl-open.c | 35 ++++++++-
36 elf/dl-support.c | 7 ++
37 elf/dl-tls.c | 16 ++---
38 elf/rtld.c | 1 +
39 sysdeps/nptl/fork.c | 3 +
40 sysdeps/generic/ldsodefs.h | 9 ++-
41 10 files changed, 235 insertions(+), 12 deletions(-)
42---
43Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=024a7640ab9ecea80e527f4e4d7f7a1868e952c5]
44Comment: This patch is refreshed for glibc 2.31. In upstream glibc 2.34 multiple src files are shuffled, updated this patch as per the code present in glibc 2.31. Removed test case.
45Signed-off-by: Akash Hadke <akash.hadke@kpit.com>
46Signed-off-by: Akash Hadke <hadkeakash4@gmail.com>
47---
48diff --git a/elf/dl-close.c b/elf/dl-close.c
49index 93ff5c96e9..cfe0f1c0c9 100644
50--- a/elf/dl-close.c
51+++ b/elf/dl-close.c
52@@ -551,6 +551,9 @@
53 size_t tls_free_end;
54 tls_free_start = tls_free_end = NO_TLS_OFFSET;
55
56+ /* Protects global and module specitic TLS state. */
57+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
58+
59 /* We modify the list of loaded objects. */
60 __rtld_lock_lock_recursive (GL(dl_load_write_lock));
61
62@@ -786,6 +789,9 @@
63 GL(dl_tls_static_used) = tls_free_start;
64 }
65
66+ /* TLS is cleaned up for the unloaded modules. */
67+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
68+
69 #ifdef SHARED
70 /* Auditing checkpoint: we have deleted all objects. */
71 if (__glibc_unlikely (do_audit))
72diff --git a/elf/dl-open.c b/elf/dl-open.c
73index 5295e931b0..6ea5dd2457 100644
74--- a/elf/dl-open.c
75+++ b/elf/dl-open.c
76@@ -57,6 +57,9 @@
77 (non-negative). */
78 unsigned int original_global_scope_pending_adds;
79
80+ /* Set to true if the end of dl_open_worker_begin was reached. */
81+ bool worker_continue;
82+
83 /* Original parameters to the program and the current environment. */
84 int argc;
85 char **argv;
86@@ -473,7 +473,7 @@
87 }
88
89 static void
90-dl_open_worker (void *a)
91+dl_open_worker_begin (void *a)
92 {
93 struct dl_open_args *args = a;
94 const char *file = args->file;
95@@ -747,6 +747,36 @@
96 if (mode & RTLD_GLOBAL)
97 add_to_global_resize (new);
98
99+ args->worker_continue = true;
100+}
101+
102+static void
103+dl_open_worker (void *a)
104+{
105+ struct dl_open_args *args = a;
106+
107+ args->worker_continue = false;
108+
109+ {
110+ /* Protects global and module specific TLS state. */
111+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
112+
113+ struct dl_exception ex;
114+ int err = _dl_catch_exception (&ex, dl_open_worker_begin, args);
115+
116+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
117+
118+ if (__glibc_unlikely (ex.errstring != NULL))
119+ /* Reraise the error. */
120+ _dl_signal_exception (err, &ex, NULL);
121+ }
122+
123+ if (!args->worker_continue)
124+ return;
125+
126+ int mode = args->mode;
127+ struct link_map *new = args->map;
128+
129 /* Run the initializer functions of new objects. Temporarily
130 disable the exception handler, so that lazy binding failures are
131 fatal. */
132diff --git a/elf/dl-support.c b/elf/dl-support.c
133index 02e2ed72f5..d99c1f1d62 100644
134--- a/elf/dl-support.c
135+++ b/elf/dl-support.c
136@@ -219,6 +219,13 @@
137 list of loaded objects while an object is added to or removed from
138 that list. */
139 __rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
140+/* This lock protects global and module specific TLS related data.
141+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
142+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
143+ accessed and when TLS related relocations are processed for a
144+ module. It was introduced to keep pthread_create accessing TLS
145+ state that is being set up. */
146+__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
147
148
149 #ifdef HAVE_AUX_VECTOR
150diff --git a/elf/dl-tls.c b/elf/dl-tls.c
151index d554ae4497..9260d2d696 100644
152--- a/elf/dl-tls.c
153+++ b/elf/dl-tls.c
154@@ -443,7 +443,7 @@
155 size_t maxgen = 0;
156
157 /* Protects global dynamic TLS related state. */
158- __rtld_lock_lock_recursive (GL(dl_load_lock));
159+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
160
161 /* Check if the current dtv is big enough. */
162 if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
163@@ -517,7 +517,7 @@
164 listp = listp->next;
165 assert (listp != NULL);
166 }
167- __rtld_lock_unlock_recursive (GL(dl_load_lock));
168+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
169
170 /* The DTV version is up-to-date now. */
171 dtv[0].counter = maxgen;
172@@ -656,7 +656,7 @@
173
174 Here the dtv needs to be updated to new_gen generation count.
175
176- This code may be called during TLS access when GL(dl_load_lock)
177+ This code may be called during TLS access when GL(dl_load_tls_lock)
178 is not held. In that case the user code has to synchronize with
179 dlopen and dlclose calls of relevant modules. A module m is
180 relevant if the generation of m <= new_gen and dlclose of m is
181@@ -778,11 +778,11 @@
182 if (__glibc_unlikely (the_map->l_tls_offset
183 != FORCED_DYNAMIC_TLS_OFFSET))
184 {
185- __rtld_lock_lock_recursive (GL(dl_load_lock));
186+ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
187 if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
188 {
189 the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
190- __rtld_lock_unlock_recursive (GL(dl_load_lock));
191+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
192 }
193 else if (__glibc_likely (the_map->l_tls_offset
194 != FORCED_DYNAMIC_TLS_OFFSET))
195@@ -794,7 +794,7 @@
196 #else
197 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
198 #endif
199- __rtld_lock_unlock_recursive (GL(dl_load_lock));
200+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
201
202 dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
203 dtv[GET_ADDR_MODULE].pointer.val = p;
204@@ -802,7 +802,7 @@
205 return (char *) p + GET_ADDR_OFFSET;
206 }
207 else
208- __rtld_lock_unlock_recursive (GL(dl_load_lock));
209+ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
210 }
211 struct dtv_pointer result = allocate_and_init (the_map);
212 dtv[GET_ADDR_MODULE].pointer = result;
213@@ -873,7 +873,7 @@
214 return NULL;
215
216 dtv_t *dtv = THREAD_DTV ();
217- /* This may be called without holding the GL(dl_load_lock). Reading
218+ /* This may be called without holding the GL(dl_load_tls_lock). Reading
219 arbitrary gen value is fine since this is best effort code. */
220 size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
221 if (__glibc_unlikely (dtv[0].counter != gen))
222diff --git a/elf/rtld.c b/elf/rtld.c
223index 8d2bba3d43..9642eb9c92 100644
224--- a/elf/rtld.c
225+++ b/elf/rtld.c
226@@ -283,6 +283,7 @@
227 #ifdef _LIBC_REENTRANT
228 ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
229 ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
230+ ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
231 #endif
232 ._dl_nns = 1,
233 ._dl_ns =
234diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
235index c471f7b15f..021691b9b7 100644
236--- a/sysdeps/nptl/fork.c
237+++ b/sysdeps/nptl/fork.c
238@@ -125,6 +125,9 @@
239 /* Reset the lock the dynamic loader uses to protect its data. */
240 __rtld_lock_initialize (GL(dl_load_lock));
241
242+ /* Reset the lock protecting dynamic TLS related data. */
243+ __rtld_lock_initialize (GL(dl_load_tls_lock));
244+
245 /* Run the handlers registered for the child. */
246 __run_fork_handlers (atfork_run_child, multiple_threads);
247 }
248diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
249index d49529da0d..9ec1511bb0 100644
250--- a/sysdeps/generic/ldsodefs.h
251+++ b/sysdeps/generic/ldsodefs.h
252@@ -369,6 +369,13 @@
253 list of loaded objects while an object is added to or removed
254 from that list. */
255 __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock)
256+ /* This lock protects global and module specific TLS related data.
257+ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
258+ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
259+ accessed and when TLS related relocations are processed for a
260+ module. It was introduced to keep pthread_create accessing TLS
261+ state that is being set up. */
262+ __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock)
263
264 /* Incremented whenever something may have been added to dl_loaded. */
265 EXTERN unsigned long long _dl_load_adds;
266@@ -1153,7 +1160,7 @@
267
268 /* Add module to slot information data. If DO_ADD is false, only the
269 required memory is allocated. Must be called with GL
270- (dl_load_lock) acquired. If the function has already been called
271+ (dl_load_tls_lock) acquired. If the function has already been called
272 for the link map L with !do_add, then this function will not raise
273 an exception, otherwise it is possible that it encounters a memory
274 allocation failure. */
275--
2762.27.0
diff --git a/meta/recipes-core/glibc/glibc/CVE-2019-25013.patch b/meta/recipes-core/glibc/glibc/CVE-2019-25013.patch
deleted file mode 100644
index 73df1da868..0000000000
--- a/meta/recipes-core/glibc/glibc/CVE-2019-25013.patch
+++ /dev/null
@@ -1,135 +0,0 @@
1From ee7a3144c9922808181009b7b3e50e852fb4999b Mon Sep 17 00:00:00 2001
2From: Andreas Schwab <schwab@suse.de>
3Date: Mon, 21 Dec 2020 08:56:43 +0530
4Subject: [PATCH] Fix buffer overrun in EUC-KR conversion module (bz #24973)
5
6The byte 0xfe as input to the EUC-KR conversion denotes a user-defined
7area and is not allowed. The from_euc_kr function used to skip two bytes
8when told to skip over the unknown designation, potentially running over
9the buffer end.
10
11Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=ee7a3144c9922808181009b7b3e50e852fb4999b]
12CVE: CVE-2019-25013
13Signed-off-by: Scott Murray <scott.murray@konsulko.com>
14[Refreshed for Dundell context; Makefile changes]
15Signed-off-by: Armin Kuster <akuster@mvista.com>
16
17---
18 iconvdata/Makefile | 3 ++-
19 iconvdata/bug-iconv13.c | 53 +++++++++++++++++++++++++++++++++++++++++
20 iconvdata/euc-kr.c | 6 +----
21 iconvdata/ksc5601.h | 6 ++---
22 4 files changed, 59 insertions(+), 9 deletions(-)
23 create mode 100644 iconvdata/bug-iconv13.c
24
25Index: git/iconvdata/Makefile
26===================================================================
27--- git.orig/iconvdata/Makefile
28+++ git/iconvdata/Makefile
29@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules
30 ifeq (yes,$(build-shared))
31 tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
32 tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
33- bug-iconv10 bug-iconv11 bug-iconv12
34+ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13
35 ifeq ($(have-thread-library),yes)
36 tests += bug-iconv3
37 endif
38Index: git/iconvdata/bug-iconv13.c
39===================================================================
40--- /dev/null
41+++ git/iconvdata/bug-iconv13.c
42@@ -0,0 +1,53 @@
43+/* bug 24973: Test EUC-KR module
44+ Copyright (C) 2020 Free Software Foundation, Inc.
45+ This file is part of the GNU C Library.
46+
47+ The GNU C Library is free software; you can redistribute it and/or
48+ modify it under the terms of the GNU Lesser General Public
49+ License as published by the Free Software Foundation; either
50+ version 2.1 of the License, or (at your option) any later version.
51+
52+ The GNU C Library is distributed in the hope that it will be useful,
53+ but WITHOUT ANY WARRANTY; without even the implied warranty of
54+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
55+ Lesser General Public License for more details.
56+
57+ You should have received a copy of the GNU Lesser General Public
58+ License along with the GNU C Library; if not, see
59+ <https://www.gnu.org/licenses/>. */
60+
61+#include <errno.h>
62+#include <iconv.h>
63+#include <stdio.h>
64+#include <support/check.h>
65+
66+static int
67+do_test (void)
68+{
69+ iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR");
70+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
71+
72+ /* 0xfe (->0x7e : row 94) and 0xc9 (->0x49 : row 41) are user-defined
73+ areas, which are not allowed and should be skipped over due to
74+ //IGNORE. The trailing 0xfe also is an incomplete sequence, which
75+ should be checked first. */
76+ char input[4] = { '\xc9', '\xa1', '\0', '\xfe' };
77+ char *inptr = input;
78+ size_t insize = sizeof (input);
79+ char output[4];
80+ char *outptr = output;
81+ size_t outsize = sizeof (output);
82+
83+ /* This used to crash due to buffer overrun. */
84+ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1);
85+ TEST_VERIFY (errno == EINVAL);
86+ /* The conversion should produce one character, the converted null
87+ character. */
88+ TEST_VERIFY (sizeof (output) - outsize == 1);
89+
90+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
91+
92+ return 0;
93+}
94+
95+#include <support/test-driver.c>
96Index: git/iconvdata/euc-kr.c
97===================================================================
98--- git.orig/iconvdata/euc-kr.c
99+++ git/iconvdata/euc-kr.c
100@@ -80,11 +80,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned c
101 \
102 if (ch <= 0x9f) \
103 ++inptr; \
104- /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \
105- user-defined areas. */ \
106- else if (__builtin_expect (ch == 0xa0, 0) \
107- || __builtin_expect (ch > 0xfe, 0) \
108- || __builtin_expect (ch == 0xc9, 0)) \
109+ else if (__glibc_unlikely (ch == 0xa0)) \
110 { \
111 /* This is illegal. */ \
112 STANDARD_FROM_LOOP_ERR_HANDLER (1); \
113Index: git/iconvdata/ksc5601.h
114===================================================================
115--- git.orig/iconvdata/ksc5601.h
116+++ git/iconvdata/ksc5601.h
117@@ -50,15 +50,15 @@ ksc5601_to_ucs4 (const unsigned char **s
118 unsigned char ch2;
119 int idx;
120
121+ if (avail < 2)
122+ return 0;
123+
124 /* row 94(0x7e) and row 41(0x49) are user-defined area in KS C 5601 */
125
126 if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e
127 || (ch - offset) == 0x49)
128 return __UNKNOWN_10646_CHAR;
129
130- if (avail < 2)
131- return 0;
132-
133 ch2 = (*s)[1];
134 if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f)
135 return __UNKNOWN_10646_CHAR;
diff --git a/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch b/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch
deleted file mode 100644
index c51fb3223a..0000000000
--- a/meta/recipes-core/glibc/glibc/CVE-2020-29562.patch
+++ /dev/null
@@ -1,156 +0,0 @@
1From 228edd356f03bf62dcf2b1335f25d43c602ee68d Mon Sep 17 00:00:00 2001
2From: Michael Colavita <mcolavita@fb.com>
3Date: Thu, 19 Nov 2020 11:44:40 -0500
4Subject: [PATCH] iconv: Fix incorrect UCS4 inner loop bounds (BZ#26923)
5
6Previously, in UCS4 conversion routines we limit the number of
7characters we examine to the minimum of the number of characters in the
8input and the number of characters in the output. This is not the
9correct behavior when __GCONV_IGNORE_ERRORS is set, as we do not consume
10an output character when we skip a code unit. Instead, track the input
11and output pointers and terminate the loop when either reaches its
12limit.
13
14This resolves assertion failures when resetting the input buffer in a step of
15iconv, which assumes that the input will be fully consumed given sufficient
16output space.
17
18Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=228edd356f03bf62dcf2b1335f25d43c602ee68d]
19CVE: CVE-2020-29562
20Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
21
22---
23 iconv/Makefile | 2 +-
24 iconv/gconv_simple.c | 16 ++++----------
25 iconv/tst-iconv8.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
26 3 files changed, 55 insertions(+), 13 deletions(-)
27 create mode 100644 iconv/tst-iconv8.c
28
29diff --git a/iconv/Makefile b/iconv/Makefile
30index 30bf996d3a..f9b51e23ec 100644
31--- a/iconv/Makefile
32+++ b/iconv/Makefile
33@@ -44,7 +44,7 @@ CFLAGS-linereader.c += -DNO_TRANSLITERATION
34 CFLAGS-simple-hash.c += -I../locale
35
36 tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \
37- tst-iconv7 tst-iconv-mt tst-iconv-opt
38+ tst-iconv7 tst-iconv8 tst-iconv-mt tst-iconv-opt
39
40 others = iconv_prog iconvconfig
41 install-others-programs = $(inst_bindir)/iconv
42diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
43index d4797fba17..963b29f246 100644
44--- a/iconv/gconv_simple.c
45+++ b/iconv/gconv_simple.c
46@@ -239,11 +239,9 @@ ucs4_internal_loop (struct __gconv_step *step,
47 int flags = step_data->__flags;
48 const unsigned char *inptr = *inptrp;
49 unsigned char *outptr = *outptrp;
50- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
51 int result;
52- size_t cnt;
53
54- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
55+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
56 {
57 uint32_t inval;
58
59@@ -307,11 +305,9 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step,
60 int flags = step_data->__flags;
61 const unsigned char *inptr = *inptrp;
62 unsigned char *outptr = *outptrp;
63- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
64 int result;
65- size_t cnt;
66
67- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
68+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
69 {
70 if (__glibc_unlikely (inptr[0] > 0x80))
71 {
72@@ -613,11 +609,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
73 int flags = step_data->__flags;
74 const unsigned char *inptr = *inptrp;
75 unsigned char *outptr = *outptrp;
76- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
77 int result;
78- size_t cnt;
79
80- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
81+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
82 {
83 uint32_t inval;
84
85@@ -684,11 +678,9 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step,
86 int flags = step_data->__flags;
87 const unsigned char *inptr = *inptrp;
88 unsigned char *outptr = *outptrp;
89- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
90 int result;
91- size_t cnt;
92
93- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
94+ for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
95 {
96 if (__glibc_unlikely (inptr[3] > 0x80))
97 {
98diff --git a/iconv/tst-iconv8.c b/iconv/tst-iconv8.c
99new file mode 100644
100index 0000000000..0b92b19f66
101--- /dev/null
102+++ b/iconv/tst-iconv8.c
103@@ -0,0 +1,50 @@
104+/* Test iconv behavior on UCS4 conversions with //IGNORE.
105+ Copyright (C) 2020 Free Software Foundation, Inc.
106+ This file is part of the GNU C Library.
107+
108+ The GNU C Library is free software; you can redistribute it and/or
109+ modify it under the terms of the GNU Lesser General Public
110+ License as published by the Free Software Foundation; either
111+ version 2.1 of the License, or (at your option) any later version.
112+
113+ The GNU C Library is distributed in the hope that it will be useful,
114+ but WITHOUT ANY WARRANTY; without even the implied warranty of
115+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
116+ Lesser General Public License for more details.
117+
118+ You should have received a copy of the GNU Lesser General Public
119+ License along with the GNU C Library; if not, see
120+ <http://www.gnu.org/licenses/>. */
121+
122+/* Derived from BZ #26923 */
123+#include <errno.h>
124+#include <iconv.h>
125+#include <stdio.h>
126+#include <support/check.h>
127+
128+static int
129+do_test (void)
130+{
131+ iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/");
132+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
133+
134+ /*
135+ * Convert sequence beginning with an irreversible character into buffer that
136+ * is too small.
137+ */
138+ char input[12] = "\xe1\x80\xa1" "AAAAAAAAA";
139+ char *inptr = input;
140+ size_t insize = sizeof (input);
141+ char output[6];
142+ char *outptr = output;
143+ size_t outsize = sizeof (output);
144+
145+ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1);
146+ TEST_VERIFY (errno == E2BIG);
147+
148+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
149+
150+ return 0;
151+}
152+
153+#include <support/test-driver.c>
154--
1552.27.0
156
diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch b/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch
new file mode 100644
index 0000000000..7561e87121
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2021-33574_1.patch
@@ -0,0 +1,68 @@
1From 42d359350510506b87101cf77202fefcbfc790cb Mon Sep 17 00:00:00 2001
2From: Andreas Schwab <schwab@linux-m68k.org>
3Date: Thu, 27 May 2021 12:49:47 +0200
4Subject: [PATCH] Use __pthread_attr_copy in mq_notify (bug 27896)
5
6Make a deep copy of the pthread attribute object to remove a potential
7use-after-free issue.
8
9Upstream-Status: Backport
10CVE: CVE-2021-33574 patch#1
11Signed-off-by: Armin Kuster <akuster@mvista.com>
12
13---
14diff --git a/NEWS b/NEWS
15index 8a20d3c4e3..be489243ac 100644
16--- a/NEWS
17+++ b/NEWS
18@@ -7,6 +7,10 @@ using `glibc' in the "product" field.
19
20 Version 2.31.1
21
22+ CVE-2021-33574: The mq_notify function has a potential use-after-free
23+ issue when using a notification type of SIGEV_THREAD and a thread
24+ attribute with a non-default affinity mask.
25+
26 The following bugs are resolved with this release:
27 [14231] stdio-common tests memory requirements
28 [19519] iconv(1) with -c option hangs on illegal multi-byte sequences
29diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c
30index f288bac477..dd47f0b777 100644
31--- a/sysdeps/unix/sysv/linux/mq_notify.c
32+++ b/sysdeps/unix/sysv/linux/mq_notify.c
33@@ -135,8 +135,11 @@ helper_thread (void *arg)
34 (void) __pthread_barrier_wait (&notify_barrier);
35 }
36 else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
37- /* The only state we keep is the copy of the thread attributes. */
38- free (data.attr);
39+ {
40+ /* The only state we keep is the copy of the thread attributes. */
41+ pthread_attr_destroy (data.attr);
42+ free (data.attr);
43+ }
44 }
45 return NULL;
46 }
47@@ -257,8 +260,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification)
48 if (data.attr == NULL)
49 return -1;
50
51- memcpy (data.attr, notification->sigev_notify_attributes,
52- sizeof (pthread_attr_t));
53+ __pthread_attr_copy (data.attr, notification->sigev_notify_attributes);
54 }
55
56 /* Construct the new request. */
57@@ -272,7 +274,10 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification)
58
59 /* If it failed, free the allocated memory. */
60 if (__glibc_unlikely (retval != 0))
61- free (data.attr);
62+ {
63+ pthread_attr_destroy (data.attr);
64+ free (data.attr);
65+ }
66
67 return retval;
68 }
diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch b/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch
new file mode 100644
index 0000000000..396cd7fc0e
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2021-33574_2.patch
@@ -0,0 +1,73 @@
1From 217b6dc298156bdb0d6aea9ea93e7e394a5ff091 Mon Sep 17 00:00:00 2001
2From: Florian Weimer <fweimer@redhat.com>
3Date: Tue, 1 Jun 2021 17:51:41 +0200
4Subject: [PATCH] Fix use of __pthread_attr_copy in mq_notify (bug 27896)
5
6__pthread_attr_copy can fail and does not initialize the attribute
7structure in that case.
8
9If __pthread_attr_copy is never called and there is no allocated
10attribute, pthread_attr_destroy should not be called, otherwise
11there is a null pointer dereference in rt/tst-mqueue6.
12
13Fixes commit 42d359350510506b87101cf77202fefcbfc790cb
14("Use __pthread_attr_copy in mq_notify (bug 27896)").
15
16Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
17
18https://sourceware.org/bugzilla/attachment.cgi?id=13497
19
20Upstream-Status: Backport
21CVE: CVE-2021-33574 patch#2
22Signed-off-by: Armin Kuster &lt;akuster@mvista.com&gt;
23
24---
25Index: git/sysdeps/unix/sysv/linux/mq_notify.c
26===================================================================
27--- git.orig/sysdeps/unix/sysv/linux/mq_notify.c
28+++ git/sysdeps/unix/sysv/linux/mq_notify.c
29@@ -260,7 +260,34 @@ mq_notify (mqd_t mqdes, const struct sig
30 if (data.attr == NULL)
31 return -1;
32
33- __pthread_attr_copy (data.attr, notification->sigev_notify_attributes);
34+ memcpy (data.attr, notification->sigev_notify_attributes,
35+ sizeof (pthread_attr_t));
36+
37+ struct pthread_attr *source =
38+ (struct pthread_attr *) (notification->sigev_notify_attributes);
39+ struct pthread_attr *target = (struct pthread_attr *) (data.attr);
40+ cpu_set_t *newp;
41+ cpu_set_t *cpuset = source->cpuset;
42+ size_t cpusetsize = source->cpusetsize;
43+
44+ /* alloc a new memory for cpuset to avoid use after free */
45+ if (cpuset != NULL && cpusetsize > 0)
46+ {
47+ newp = (cpu_set_t *) malloc (cpusetsize);
48+ if (newp == NULL)
49+ {
50+ free(data.attr);
51+ return -1;
52+ }
53+
54+ memcpy (newp, cpuset, cpusetsize);
55+ target->cpuset = newp;
56+ }
57+ else
58+ {
59+ target->cpuset = NULL;
60+ target->cpusetsize = 0;
61+ }
62 }
63
64 /* Construct the new request. */
65@@ -273,7 +300,7 @@ mq_notify (mqd_t mqdes, const struct sig
66 int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se);
67
68 /* If it failed, free the allocated memory. */
69- if (__glibc_unlikely (retval != 0))
70+ if (retval != 0 && data.attr != NULL)
71 {
72 pthread_attr_destroy (data.attr);
73 free (data.attr);
diff --git a/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch b/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch
new file mode 100644
index 0000000000..36fd4a61b2
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2021-38604.patch
@@ -0,0 +1,41 @@
1From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001
2From: Nikita Popov <npv1310@gmail.com>
3Date: Mon, 9 Aug 2021 20:17:34 +0530
4Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213)
5
6Helper thread frees copied attribute on NOTIFY_REMOVED message
7received from the OS kernel. Unfortunately, it fails to check whether
8copied attribute actually exists (data.attr != NULL). This worked
9earlier because free() checks passed pointer before actually
10attempting to release corresponding memory. But
11__pthread_attr_destroy assumes pointer is not NULL.
12
13So passing NULL pointer to __pthread_attr_destroy will result in
14segmentation fault. This scenario is possible if
15notification->sigev_notify_attributes == NULL (which means default
16thread attributes should be used).
17
18Signed-off-by: Nikita Popov <npv1310@gmail.com>
19Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
20
21Upstream-Status: Backport
22CVE: CVE-2021-38604
23Signed-off-by: Armin Kuser <akuster@mvista.com>
24
25---
26 sysdeps/unix/sysv/linux/mq_notify.c | 2 +-
27 1 file changed, 1 insertion(+), 1 deletion(-)
28
29Index: git/sysdeps/unix/sysv/linux/mq_notify.c
30===================================================================
31--- git.orig/sysdeps/unix/sysv/linux/mq_notify.c
32+++ git/sysdeps/unix/sysv/linux/mq_notify.c
33@@ -134,7 +134,7 @@ helper_thread (void *arg)
34 to wait until it is done with it. */
35 (void) __pthread_barrier_wait (&notify_barrier);
36 }
37- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
38+ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL)
39 {
40 /* The only state we keep is the copy of the thread attributes. */
41 pthread_attr_destroy (data.attr);
diff --git a/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch b/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch
new file mode 100644
index 0000000000..10c7e5666d
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2023-0687.patch
@@ -0,0 +1,82 @@
1From 952aff5c00ad7c6b83c3f310f2643939538827f8 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?=
3 =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru>
4Date: Sat, 4 Feb 2023 14:41:38 +0300
5Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444)
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10The `__monstartup()` allocates a buffer used to store all the data
11accumulated by the monitor.
12
13The size of this buffer depends on the size of the internal structures
14used and the address range for which the monitor is activated, as well
15as on the maximum density of call instructions and/or callable functions
16that could be potentially on a segment of executable code.
17
18In particular a hash table of arcs is placed at the end of this buffer.
19The size of this hash table is calculated in bytes as
20 p->fromssize = p->textsize / HASHFRACTION;
21
22but actually should be
23 p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
24
25This results in writing beyond the end of the allocated buffer when an
26added arc corresponds to a call near from the end of the monitored
27address range, since `_mcount()` check the incoming caller address for
28monitored range but not the intermediate result hash-like index that
29uses to write into the table.
30
31It should be noted that when the results are output to `gmon.out`, the
32table is read to the last element calculated from the allocated size in
33bytes, so the arcs stored outside the buffer boundary did not fall into
34`gprof` for analysis. Thus this "feature" help me to found this bug
35during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438
36
37Just in case, I will explicitly note that the problem breaks the
38`make test t=gmon/tst-gmon-dso` added for Bug 29438.
39There, the arc of the `f3()` call disappears from the output, since in
40the DSO case, the call to `f3` is located close to the end of the
41monitored range.
42
43Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
44
45Another minor error seems a related typo in the calculation of
46`kcountsize`, but since kcounts are smaller than froms, this is
47actually to align the p->froms data.
48
49Co-authored-by: DJ Delorie <dj@redhat.com>
50Reviewed-by: Carlos O'Donell <carlos@redhat.com>
51
52Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commit;h=801af9fafd4689337ebf27260aa115335a0cb2bc]
53CVE: CVE-2023-0687
54Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
55---
56 gmon/gmon.c | 4 +++-
57 1 file changed, 3 insertions(+), 1 deletion(-)
58
59diff --git a/gmon/gmon.c b/gmon/gmon.c
60index dee6480..bf76358 100644
61--- a/gmon/gmon.c
62+++ b/gmon/gmon.c
63@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc)
64 p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
65 p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
66 p->textsize = p->highpc - p->lowpc;
67+ /* This looks like a typo, but it's here to align the p->froms
68+ section. */
69 p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms));
70 p->hashfraction = HASHFRACTION;
71 p->log_hashfraction = -1;
72@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc)
73 instead of integer division. Precompute shift amount. */
74 p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
75 }
76- p->fromssize = p->textsize / HASHFRACTION;
77+ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
78 p->tolimit = p->textsize * ARCDENSITY / 100;
79 if (p->tolimit < MINARCS)
80 p->tolimit = MINARCS;
81--
822.7.4
diff --git a/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch b/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch
new file mode 100644
index 0000000000..c7db4038c2
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2023-4813.patch
@@ -0,0 +1,986 @@
1From 1c37b8022e8763fedbb3f79c02e05c6acfe5a215 Mon Sep 17 00:00:00 2001
2From: Siddhesh Poyarekar <siddhesh@sourceware.org>
3Date: Thu, 17 Mar 2022 11:44:34 +0530
4Subject: [PATCH] Simplify allocations and fix merge and continue actions [BZ
5 #28931]
6
7Allocations for address tuples is currently a bit confusing because of
8the pointer chasing through PAT, making it hard to observe the sequence
9in which allocations have been made. Narrow scope of the pointer
10chasing through PAT so that it is only used where necessary.
11
12This also tightens actions behaviour with the hosts database in
13getaddrinfo to comply with the manual text. The "continue" action
14discards previous results and the "merge" action results in an immedate
15lookup failure. Consequently, chaining of allocations across modules is
16no longer necessary, thus opening up cleanup opportunities.
17
18A test has been added that checks some combinations to ensure that they
19work correctly.
20
21Resolves: BZ #28931
22
23CVE: CVE-2023-4813
24Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=1c37b8022e8763fedbb3f79c02e05c6acfe5a215]
25Comments: Hunks refreshed
26
27Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
28Reviewed-by: DJ Delorie <dj@redhat.com>
29Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com>
30---
31 nss/Makefile | 1 +
32 nss/tst-nss-gai-actions.c | 149 ++++++
33 nss/tst-nss-gai-actions.root/etc/host.conf | 1 +
34 nss/tst-nss-gai-actions.root/etc/hosts | 508 +++++++++++++++++++++
35 sysdeps/posix/getaddrinfo.c | 143 +++---
36 5 files changed, 750 insertions(+), 52 deletions(-)
37 create mode 100644 nss/tst-nss-gai-actions.c
38 create mode 100644 nss/tst-nss-gai-actions.root/etc/host.conf
39 create mode 100644 nss/tst-nss-gai-actions.root/etc/hosts
40
41diff --git a/nss/Makefile b/nss/Makefile
42index 42a59535cb..d8b06b44fb 100644
43--- a/nss/Makefile
44+++ b/nss/Makefile
45@@ -61,6 +61,7 @@
46
47 tests-container = \
48 tst-nss-test3 \
49+ tst-nss-gai-actions \
50 tst-nss-files-hosts-long \
51 tst-nss-db-endpwent \
52 tst-nss-db-endgrent
53diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c
54new file mode 100644
55index 0000000000..efca6cd183
56--- /dev/null
57+++ b/nss/tst-nss-gai-actions.c
58@@ -0,0 +1,149 @@
59+/* Test continue and merge NSS actions for getaddrinfo.
60+ Copyright The GNU Toolchain Authors.
61+ This file is part of the GNU C Library.
62+
63+ The GNU C Library is free software; you can redistribute it and/or
64+ modify it under the terms of the GNU Lesser General Public
65+ License as published by the Free Software Foundation; either
66+ version 2.1 of the License, or (at your option) any later version.
67+
68+ The GNU C Library is distributed in the hope that it will be useful,
69+ but WITHOUT ANY WARRANTY; without even the implied warranty of
70+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
71+ Lesser General Public License for more details.
72+
73+ You should have received a copy of the GNU Lesser General Public
74+ License along with the GNU C Library; if not, see
75+ <https://www.gnu.org/licenses/>. */
76+
77+#include <dlfcn.h>
78+#include <gnu/lib-names.h>
79+#include <nss.h>
80+#include <stdio.h>
81+#include <stdlib.h>
82+#include <string.h>
83+
84+#include <support/check.h>
85+#include <support/format_nss.h>
86+#include <support/support.h>
87+#include <support/xstdio.h>
88+#include <support/xunistd.h>
89+
90+enum
91+{
92+ ACTION_MERGE = 0,
93+ ACTION_CONTINUE,
94+};
95+
96+static const char *
97+family_str (int family)
98+{
99+ switch (family)
100+ {
101+ case AF_UNSPEC:
102+ return "AF_UNSPEC";
103+ case AF_INET:
104+ return "AF_INET";
105+ default:
106+ __builtin_unreachable ();
107+ }
108+}
109+
110+static const char *
111+action_str (int action)
112+{
113+ switch (action)
114+ {
115+ case ACTION_MERGE:
116+ return "merge";
117+ case ACTION_CONTINUE:
118+ return "continue";
119+ default:
120+ __builtin_unreachable ();
121+ }
122+}
123+
124+static void
125+do_one_test (int action, int family, bool canon)
126+{
127+ struct addrinfo hints =
128+ {
129+ .ai_family = family,
130+ };
131+
132+ struct addrinfo *ai;
133+
134+ if (canon)
135+ hints.ai_flags = AI_CANONNAME;
136+
137+ printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n",
138+ action_str (action), family_str (family),
139+ canon ? "AI_CANONNAME" : "");
140+
141+ int ret = getaddrinfo ("example.org", "80", &hints, &ai);
142+
143+ switch (action)
144+ {
145+ case ACTION_MERGE:
146+ if (ret == 0)
147+ {
148+ char *formatted = support_format_addrinfo (ai, ret);
149+
150+ printf ("merge unexpectedly succeeded:\n %s\n", formatted);
151+ support_record_failure ();
152+ free (formatted);
153+ }
154+ else
155+ return;
156+ case ACTION_CONTINUE:
157+ {
158+ char *formatted = support_format_addrinfo (ai, ret);
159+
160+ /* Verify that the result appears exactly once. */
161+ const char *expected = "address: STREAM/TCP 192.0.0.1 80\n"
162+ "address: DGRAM/UDP 192.0.0.1 80\n"
163+ "address: RAW/IP 192.0.0.1 80\n";
164+
165+ const char *contains = strstr (formatted, expected);
166+ const char *contains2 = NULL;
167+
168+ if (contains != NULL)
169+ contains2 = strstr (contains + strlen (expected), expected);
170+
171+ if (contains == NULL || contains2 != NULL)
172+ {
173+ printf ("continue failed:\n%s\n", formatted);
174+ support_record_failure ();
175+ }
176+
177+ free (formatted);
178+ break;
179+ }
180+ default:
181+ __builtin_unreachable ();
182+ }
183+}
184+
185+static void
186+do_one_test_set (int action)
187+{
188+ char buf[32];
189+
190+ snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files",
191+ action_str (action));
192+ __nss_configure_lookup ("hosts", buf);
193+
194+ do_one_test (action, AF_UNSPEC, false);
195+ do_one_test (action, AF_INET, false);
196+ do_one_test (action, AF_INET, true);
197+}
198+
199+static int
200+do_test (void)
201+{
202+ do_one_test_set (ACTION_CONTINUE);
203+ do_one_test_set (ACTION_MERGE);
204+ return 0;
205+}
206+
207+#include <support/test-driver.c>
208diff --git a/nss/tst-nss-gai-actions.root/etc/host.conf b/nss/tst-nss-gai-actions.root/etc/host.conf
209new file mode 100644
210index 0000000000..d1a59f73a9
211--- /dev/null
212+++ b/nss/tst-nss-gai-actions.root/etc/host.conf
213@@ -0,0 +1 @@
214+multi on
215diff --git a/nss/tst-nss-gai-actions.root/etc/hosts b/nss/tst-nss-gai-actions.root/etc/hosts
216new file mode 100644
217index 0000000000..50ce9774dc
218--- /dev/null
219+++ b/nss/tst-nss-gai-actions.root/etc/hosts
220@@ -0,0 +1,508 @@
221+192.0.0.1 example.org
222+192.0.0.2 example.org
223+192.0.0.3 example.org
224+192.0.0.4 example.org
225+192.0.0.5 example.org
226+192.0.0.6 example.org
227+192.0.0.7 example.org
228+192.0.0.8 example.org
229+192.0.0.9 example.org
230+192.0.0.10 example.org
231+192.0.0.11 example.org
232+192.0.0.12 example.org
233+192.0.0.13 example.org
234+192.0.0.14 example.org
235+192.0.0.15 example.org
236+192.0.0.16 example.org
237+192.0.0.17 example.org
238+192.0.0.18 example.org
239+192.0.0.19 example.org
240+192.0.0.20 example.org
241+192.0.0.21 example.org
242+192.0.0.22 example.org
243+192.0.0.23 example.org
244+192.0.0.24 example.org
245+192.0.0.25 example.org
246+192.0.0.26 example.org
247+192.0.0.27 example.org
248+192.0.0.28 example.org
249+192.0.0.29 example.org
250+192.0.0.30 example.org
251+192.0.0.31 example.org
252+192.0.0.32 example.org
253+192.0.0.33 example.org
254+192.0.0.34 example.org
255+192.0.0.35 example.org
256+192.0.0.36 example.org
257+192.0.0.37 example.org
258+192.0.0.38 example.org
259+192.0.0.39 example.org
260+192.0.0.40 example.org
261+192.0.0.41 example.org
262+192.0.0.42 example.org
263+192.0.0.43 example.org
264+192.0.0.44 example.org
265+192.0.0.45 example.org
266+192.0.0.46 example.org
267+192.0.0.47 example.org
268+192.0.0.48 example.org
269+192.0.0.49 example.org
270+192.0.0.50 example.org
271+192.0.0.51 example.org
272+192.0.0.52 example.org
273+192.0.0.53 example.org
274+192.0.0.54 example.org
275+192.0.0.55 example.org
276+192.0.0.56 example.org
277+192.0.0.57 example.org
278+192.0.0.58 example.org
279+192.0.0.59 example.org
280+192.0.0.60 example.org
281+192.0.0.61 example.org
282+192.0.0.62 example.org
283+192.0.0.63 example.org
284+192.0.0.64 example.org
285+192.0.0.65 example.org
286+192.0.0.66 example.org
287+192.0.0.67 example.org
288+192.0.0.68 example.org
289+192.0.0.69 example.org
290+192.0.0.70 example.org
291+192.0.0.71 example.org
292+192.0.0.72 example.org
293+192.0.0.73 example.org
294+192.0.0.74 example.org
295+192.0.0.75 example.org
296+192.0.0.76 example.org
297+192.0.0.77 example.org
298+192.0.0.78 example.org
299+192.0.0.79 example.org
300+192.0.0.80 example.org
301+192.0.0.81 example.org
302+192.0.0.82 example.org
303+192.0.0.83 example.org
304+192.0.0.84 example.org
305+192.0.0.85 example.org
306+192.0.0.86 example.org
307+192.0.0.87 example.org
308+192.0.0.88 example.org
309+192.0.0.89 example.org
310+192.0.0.90 example.org
311+192.0.0.91 example.org
312+192.0.0.92 example.org
313+192.0.0.93 example.org
314+192.0.0.94 example.org
315+192.0.0.95 example.org
316+192.0.0.96 example.org
317+192.0.0.97 example.org
318+192.0.0.98 example.org
319+192.0.0.99 example.org
320+192.0.0.100 example.org
321+192.0.0.101 example.org
322+192.0.0.102 example.org
323+192.0.0.103 example.org
324+192.0.0.104 example.org
325+192.0.0.105 example.org
326+192.0.0.106 example.org
327+192.0.0.107 example.org
328+192.0.0.108 example.org
329+192.0.0.109 example.org
330+192.0.0.110 example.org
331+192.0.0.111 example.org
332+192.0.0.112 example.org
333+192.0.0.113 example.org
334+192.0.0.114 example.org
335+192.0.0.115 example.org
336+192.0.0.116 example.org
337+192.0.0.117 example.org
338+192.0.0.118 example.org
339+192.0.0.119 example.org
340+192.0.0.120 example.org
341+192.0.0.121 example.org
342+192.0.0.122 example.org
343+192.0.0.123 example.org
344+192.0.0.124 example.org
345+192.0.0.125 example.org
346+192.0.0.126 example.org
347+192.0.0.127 example.org
348+192.0.0.128 example.org
349+192.0.0.129 example.org
350+192.0.0.130 example.org
351+192.0.0.131 example.org
352+192.0.0.132 example.org
353+192.0.0.133 example.org
354+192.0.0.134 example.org
355+192.0.0.135 example.org
356+192.0.0.136 example.org
357+192.0.0.137 example.org
358+192.0.0.138 example.org
359+192.0.0.139 example.org
360+192.0.0.140 example.org
361+192.0.0.141 example.org
362+192.0.0.142 example.org
363+192.0.0.143 example.org
364+192.0.0.144 example.org
365+192.0.0.145 example.org
366+192.0.0.146 example.org
367+192.0.0.147 example.org
368+192.0.0.148 example.org
369+192.0.0.149 example.org
370+192.0.0.150 example.org
371+192.0.0.151 example.org
372+192.0.0.152 example.org
373+192.0.0.153 example.org
374+192.0.0.154 example.org
375+192.0.0.155 example.org
376+192.0.0.156 example.org
377+192.0.0.157 example.org
378+192.0.0.158 example.org
379+192.0.0.159 example.org
380+192.0.0.160 example.org
381+192.0.0.161 example.org
382+192.0.0.162 example.org
383+192.0.0.163 example.org
384+192.0.0.164 example.org
385+192.0.0.165 example.org
386+192.0.0.166 example.org
387+192.0.0.167 example.org
388+192.0.0.168 example.org
389+192.0.0.169 example.org
390+192.0.0.170 example.org
391+192.0.0.171 example.org
392+192.0.0.172 example.org
393+192.0.0.173 example.org
394+192.0.0.174 example.org
395+192.0.0.175 example.org
396+192.0.0.176 example.org
397+192.0.0.177 example.org
398+192.0.0.178 example.org
399+192.0.0.179 example.org
400+192.0.0.180 example.org
401+192.0.0.181 example.org
402+192.0.0.182 example.org
403+192.0.0.183 example.org
404+192.0.0.184 example.org
405+192.0.0.185 example.org
406+192.0.0.186 example.org
407+192.0.0.187 example.org
408+192.0.0.188 example.org
409+192.0.0.189 example.org
410+192.0.0.190 example.org
411+192.0.0.191 example.org
412+192.0.0.192 example.org
413+192.0.0.193 example.org
414+192.0.0.194 example.org
415+192.0.0.195 example.org
416+192.0.0.196 example.org
417+192.0.0.197 example.org
418+192.0.0.198 example.org
419+192.0.0.199 example.org
420+192.0.0.200 example.org
421+192.0.0.201 example.org
422+192.0.0.202 example.org
423+192.0.0.203 example.org
424+192.0.0.204 example.org
425+192.0.0.205 example.org
426+192.0.0.206 example.org
427+192.0.0.207 example.org
428+192.0.0.208 example.org
429+192.0.0.209 example.org
430+192.0.0.210 example.org
431+192.0.0.211 example.org
432+192.0.0.212 example.org
433+192.0.0.213 example.org
434+192.0.0.214 example.org
435+192.0.0.215 example.org
436+192.0.0.216 example.org
437+192.0.0.217 example.org
438+192.0.0.218 example.org
439+192.0.0.219 example.org
440+192.0.0.220 example.org
441+192.0.0.221 example.org
442+192.0.0.222 example.org
443+192.0.0.223 example.org
444+192.0.0.224 example.org
445+192.0.0.225 example.org
446+192.0.0.226 example.org
447+192.0.0.227 example.org
448+192.0.0.228 example.org
449+192.0.0.229 example.org
450+192.0.0.230 example.org
451+192.0.0.231 example.org
452+192.0.0.232 example.org
453+192.0.0.233 example.org
454+192.0.0.234 example.org
455+192.0.0.235 example.org
456+192.0.0.236 example.org
457+192.0.0.237 example.org
458+192.0.0.238 example.org
459+192.0.0.239 example.org
460+192.0.0.240 example.org
461+192.0.0.241 example.org
462+192.0.0.242 example.org
463+192.0.0.243 example.org
464+192.0.0.244 example.org
465+192.0.0.245 example.org
466+192.0.0.246 example.org
467+192.0.0.247 example.org
468+192.0.0.248 example.org
469+192.0.0.249 example.org
470+192.0.0.250 example.org
471+192.0.0.251 example.org
472+192.0.0.252 example.org
473+192.0.0.253 example.org
474+192.0.0.254 example.org
475+192.0.1.1 example.org
476+192.0.1.2 example.org
477+192.0.1.3 example.org
478+192.0.1.4 example.org
479+192.0.1.5 example.org
480+192.0.1.6 example.org
481+192.0.1.7 example.org
482+192.0.1.8 example.org
483+192.0.1.9 example.org
484+192.0.1.10 example.org
485+192.0.1.11 example.org
486+192.0.1.12 example.org
487+192.0.1.13 example.org
488+192.0.1.14 example.org
489+192.0.1.15 example.org
490+192.0.1.16 example.org
491+192.0.1.17 example.org
492+192.0.1.18 example.org
493+192.0.1.19 example.org
494+192.0.1.20 example.org
495+192.0.1.21 example.org
496+192.0.1.22 example.org
497+192.0.1.23 example.org
498+192.0.1.24 example.org
499+192.0.1.25 example.org
500+192.0.1.26 example.org
501+192.0.1.27 example.org
502+192.0.1.28 example.org
503+192.0.1.29 example.org
504+192.0.1.30 example.org
505+192.0.1.31 example.org
506+192.0.1.32 example.org
507+192.0.1.33 example.org
508+192.0.1.34 example.org
509+192.0.1.35 example.org
510+192.0.1.36 example.org
511+192.0.1.37 example.org
512+192.0.1.38 example.org
513+192.0.1.39 example.org
514+192.0.1.40 example.org
515+192.0.1.41 example.org
516+192.0.1.42 example.org
517+192.0.1.43 example.org
518+192.0.1.44 example.org
519+192.0.1.45 example.org
520+192.0.1.46 example.org
521+192.0.1.47 example.org
522+192.0.1.48 example.org
523+192.0.1.49 example.org
524+192.0.1.50 example.org
525+192.0.1.51 example.org
526+192.0.1.52 example.org
527+192.0.1.53 example.org
528+192.0.1.54 example.org
529+192.0.1.55 example.org
530+192.0.1.56 example.org
531+192.0.1.57 example.org
532+192.0.1.58 example.org
533+192.0.1.59 example.org
534+192.0.1.60 example.org
535+192.0.1.61 example.org
536+192.0.1.62 example.org
537+192.0.1.63 example.org
538+192.0.1.64 example.org
539+192.0.1.65 example.org
540+192.0.1.66 example.org
541+192.0.1.67 example.org
542+192.0.1.68 example.org
543+192.0.1.69 example.org
544+192.0.1.70 example.org
545+192.0.1.71 example.org
546+192.0.1.72 example.org
547+192.0.1.73 example.org
548+192.0.1.74 example.org
549+192.0.1.75 example.org
550+192.0.1.76 example.org
551+192.0.1.77 example.org
552+192.0.1.78 example.org
553+192.0.1.79 example.org
554+192.0.1.80 example.org
555+192.0.1.81 example.org
556+192.0.1.82 example.org
557+192.0.1.83 example.org
558+192.0.1.84 example.org
559+192.0.1.85 example.org
560+192.0.1.86 example.org
561+192.0.1.87 example.org
562+192.0.1.88 example.org
563+192.0.1.89 example.org
564+192.0.1.90 example.org
565+192.0.1.91 example.org
566+192.0.1.92 example.org
567+192.0.1.93 example.org
568+192.0.1.94 example.org
569+192.0.1.95 example.org
570+192.0.1.96 example.org
571+192.0.1.97 example.org
572+192.0.1.98 example.org
573+192.0.1.99 example.org
574+192.0.1.100 example.org
575+192.0.1.101 example.org
576+192.0.1.102 example.org
577+192.0.1.103 example.org
578+192.0.1.104 example.org
579+192.0.1.105 example.org
580+192.0.1.106 example.org
581+192.0.1.107 example.org
582+192.0.1.108 example.org
583+192.0.1.109 example.org
584+192.0.1.110 example.org
585+192.0.1.111 example.org
586+192.0.1.112 example.org
587+192.0.1.113 example.org
588+192.0.1.114 example.org
589+192.0.1.115 example.org
590+192.0.1.116 example.org
591+192.0.1.117 example.org
592+192.0.1.118 example.org
593+192.0.1.119 example.org
594+192.0.1.120 example.org
595+192.0.1.121 example.org
596+192.0.1.122 example.org
597+192.0.1.123 example.org
598+192.0.1.124 example.org
599+192.0.1.125 example.org
600+192.0.1.126 example.org
601+192.0.1.127 example.org
602+192.0.1.128 example.org
603+192.0.1.129 example.org
604+192.0.1.130 example.org
605+192.0.1.131 example.org
606+192.0.1.132 example.org
607+192.0.1.133 example.org
608+192.0.1.134 example.org
609+192.0.1.135 example.org
610+192.0.1.136 example.org
611+192.0.1.137 example.org
612+192.0.1.138 example.org
613+192.0.1.139 example.org
614+192.0.1.140 example.org
615+192.0.1.141 example.org
616+192.0.1.142 example.org
617+192.0.1.143 example.org
618+192.0.1.144 example.org
619+192.0.1.145 example.org
620+192.0.1.146 example.org
621+192.0.1.147 example.org
622+192.0.1.148 example.org
623+192.0.1.149 example.org
624+192.0.1.150 example.org
625+192.0.1.151 example.org
626+192.0.1.152 example.org
627+192.0.1.153 example.org
628+192.0.1.154 example.org
629+192.0.1.155 example.org
630+192.0.1.156 example.org
631+192.0.1.157 example.org
632+192.0.1.158 example.org
633+192.0.1.159 example.org
634+192.0.1.160 example.org
635+192.0.1.161 example.org
636+192.0.1.162 example.org
637+192.0.1.163 example.org
638+192.0.1.164 example.org
639+192.0.1.165 example.org
640+192.0.1.166 example.org
641+192.0.1.167 example.org
642+192.0.1.168 example.org
643+192.0.1.169 example.org
644+192.0.1.170 example.org
645+192.0.1.171 example.org
646+192.0.1.172 example.org
647+192.0.1.173 example.org
648+192.0.1.174 example.org
649+192.0.1.175 example.org
650+192.0.1.176 example.org
651+192.0.1.177 example.org
652+192.0.1.178 example.org
653+192.0.1.179 example.org
654+192.0.1.180 example.org
655+192.0.1.181 example.org
656+192.0.1.182 example.org
657+192.0.1.183 example.org
658+192.0.1.184 example.org
659+192.0.1.185 example.org
660+192.0.1.186 example.org
661+192.0.1.187 example.org
662+192.0.1.188 example.org
663+192.0.1.189 example.org
664+192.0.1.190 example.org
665+192.0.1.191 example.org
666+192.0.1.192 example.org
667+192.0.1.193 example.org
668+192.0.1.194 example.org
669+192.0.1.195 example.org
670+192.0.1.196 example.org
671+192.0.1.197 example.org
672+192.0.1.198 example.org
673+192.0.1.199 example.org
674+192.0.1.200 example.org
675+192.0.1.201 example.org
676+192.0.1.202 example.org
677+192.0.1.203 example.org
678+192.0.1.204 example.org
679+192.0.1.205 example.org
680+192.0.1.206 example.org
681+192.0.1.207 example.org
682+192.0.1.208 example.org
683+192.0.1.209 example.org
684+192.0.1.210 example.org
685+192.0.1.211 example.org
686+192.0.1.212 example.org
687+192.0.1.213 example.org
688+192.0.1.214 example.org
689+192.0.1.215 example.org
690+192.0.1.216 example.org
691+192.0.1.217 example.org
692+192.0.1.218 example.org
693+192.0.1.219 example.org
694+192.0.1.220 example.org
695+192.0.1.221 example.org
696+192.0.1.222 example.org
697+192.0.1.223 example.org
698+192.0.1.224 example.org
699+192.0.1.225 example.org
700+192.0.1.226 example.org
701+192.0.1.227 example.org
702+192.0.1.228 example.org
703+192.0.1.229 example.org
704+192.0.1.230 example.org
705+192.0.1.231 example.org
706+192.0.1.232 example.org
707+192.0.1.233 example.org
708+192.0.1.234 example.org
709+192.0.1.235 example.org
710+192.0.1.236 example.org
711+192.0.1.237 example.org
712+192.0.1.238 example.org
713+192.0.1.239 example.org
714+192.0.1.240 example.org
715+192.0.1.241 example.org
716+192.0.1.242 example.org
717+192.0.1.243 example.org
718+192.0.1.244 example.org
719+192.0.1.245 example.org
720+192.0.1.246 example.org
721+192.0.1.247 example.org
722+192.0.1.248 example.org
723+192.0.1.249 example.org
724+192.0.1.250 example.org
725+192.0.1.251 example.org
726+192.0.1.252 example.org
727+192.0.1.253 example.org
728+192.0.1.254 example.org
729diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
730index 18dccd5924..3d9bea60c6 100644
731--- a/sysdeps/posix/getaddrinfo.c
732+++ b/sysdeps/posix/getaddrinfo.c
733@@ -458,11 +458,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
734
735 if (name != NULL)
736 {
737- at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
738- at->family = AF_UNSPEC;
739- at->scopeid = 0;
740- at->next = NULL;
741-
742 if (req->ai_flags & AI_IDN)
743 {
744 char *out;
745@@ -473,13 +468,21 @@ gaih_inet (const char *name, const struct gaih_service *service,
746 malloc_name = true;
747 }
748
749- if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
750+ uint32_t addr[4];
751+ if (__inet_aton_exact (name, (struct in_addr *) addr) != 0)
752 {
753+ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
754+ at->scopeid = 0;
755+ at->next = NULL;
756+
757 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
758- at->family = AF_INET;
759+ {
760+ memcpy (at->addr, addr, sizeof (at->addr));
761+ at->family = AF_INET;
762+ }
763 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
764 {
765- at->addr[3] = at->addr[0];
766+ at->addr[3] = addr[0];
767 at->addr[2] = htonl (0xffff);
768 at->addr[1] = 0;
769 at->addr[0] = 0;
770@@ -505,49 +505,62 @@
771
772 if (req->ai_flags & AI_CANONNAME)
773 canon = name;
774+
775+ goto process_list;
776 }
777- else if (at->family == AF_UNSPEC)
778+
779+ char *scope_delim = strchr (name, SCOPE_DELIMITER);
780+ int e;
781+
782+ if (scope_delim == NULL)
783+ e = inet_pton (AF_INET6, name, addr);
784+ else
785+ e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr);
786+
787+ if (e > 0)
788 {
789- char *scope_delim = strchr (name, SCOPE_DELIMITER);
790- int e;
791- if (scope_delim == NULL)
792- e = inet_pton (AF_INET6, name, at->addr);
793+ at = alloca_account (sizeof (struct gaih_addrtuple),
794+ alloca_used);
795+ at->scopeid = 0;
796+ at->next = NULL;
797+
798+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
799+ {
800+ memcpy (at->addr, addr, sizeof (at->addr));
801+ at->family = AF_INET6;
802+ }
803+ else if (req->ai_family == AF_INET
804+ && IN6_IS_ADDR_V4MAPPED (addr))
805+ {
806+ at->addr[0] = addr[3];
807+ at->addr[1] = addr[1];
808+ at->addr[2] = addr[2];
809+ at->addr[3] = addr[3];
810+ at->family = AF_INET;
811+ }
812 else
813- e = __inet_pton_length (AF_INET6, name, scope_delim - name,
814- at->addr);
815- if (e > 0)
816 {
817- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
818- at->family = AF_INET6;
819- else if (req->ai_family == AF_INET
820- && IN6_IS_ADDR_V4MAPPED (at->addr))
821- {
822- at->addr[0] = at->addr[3];
823- at->family = AF_INET;
824- }
825- else
826- {
827- result = -EAI_ADDRFAMILY;
828- goto free_and_return;
829- }
830-
831- if (scope_delim != NULL
832- && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
833- scope_delim + 1,
834- &at->scopeid) != 0)
835- {
836- result = -EAI_NONAME;
837- goto free_and_return;
838- }
839+ result = -EAI_ADDRFAMILY;
840+ goto free_and_return;
841+ }
842
843- if (req->ai_flags & AI_CANONNAME)
844- canon = name;
845+ if (scope_delim != NULL
846+ && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
847+ scope_delim + 1,
848+ &at->scopeid) != 0)
849+ {
850+ result = -EAI_NONAME;
851+ goto free_and_return;
852 }
853+
854+ if (req->ai_flags & AI_CANONNAME)
855+ canon = name;
856+
857+ goto process_list;
858 }
859
860- if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
861+ if ((req->ai_flags & AI_NUMERICHOST) == 0)
862 {
863- struct gaih_addrtuple **pat = &at;
864 int no_data = 0;
865 int no_inet6_data = 0;
866 service_user *nip;
867@@ -543,6 +559,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
868 enum nss_status status = NSS_STATUS_UNAVAIL;
869 int no_more;
870 struct resolv_context *res_ctx = NULL;
871+ bool do_merge = false;
872
873 /* If we do not have to look for IPv6 addresses or the canonical
874 name, use the simple, old functions, which do not support
875@@ -579,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
876 result = -EAI_MEMORY;
877 goto free_and_return;
878 }
879- *pat = addrmem;
880+ at = addrmem;
881 }
882 else
883 {
884@@ -632,6 +649,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
885 }
886
887 struct gaih_addrtuple *addrfree = addrmem;
888+ struct gaih_addrtuple **pat = &at;
889+
890 for (int i = 0; i < air->naddrs; ++i)
891 {
892 socklen_t size = (air->family[i] == AF_INET
893@@ -695,12 +714,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
894
895 free (air);
896
897- if (at->family == AF_UNSPEC)
898- {
899- result = -EAI_NONAME;
900- goto free_and_return;
901- }
902-
903 goto process_list;
904 }
905 else if (err == 0)
906@@ -750,6 +763,22 @@
907
908 while (!no_more)
909 {
910+ /* Always start afresh; continue should discard previous results
911+ and the hosts database does not support merge. */
912+ at = NULL;
913+ free (canonbuf);
914+ free (addrmem);
915+ canon = canonbuf = NULL;
916+ addrmem = NULL;
917+ got_ipv6 = false;
918+
919+ if (do_merge)
920+ {
921+ __set_h_errno (NETDB_INTERNAL);
922+ __set_errno (EBUSY);
923+ break;
924+ }
925+
926 no_data = 0;
927 nss_gethostbyname4_r fct4 = NULL;
928
929@@ -744,12 +773,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
930 {
931 while (1)
932 {
933- status = DL_CALL_FCT (fct4, (name, pat,
934+ status = DL_CALL_FCT (fct4, (name, &at,
935 tmpbuf->data, tmpbuf->length,
936 &errno, &h_errno,
937 NULL));
938 if (status == NSS_STATUS_SUCCESS)
939 break;
940+ /* gethostbyname4_r may write into AT, so reset it. */
941+ at = NULL;
942 if (status != NSS_STATUS_TRYAGAIN
943 || errno != ERANGE || h_errno != NETDB_INTERNAL)
944 {
945@@ -774,7 +805,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
946 no_data = 1;
947
948 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
949- canon = (*pat)->name;
950+ canon = at->name;
951+
952+ struct gaih_addrtuple **pat = &at;
953
954 while (*pat != NULL)
955 {
956@@ -826,6 +859,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
957
958 if (fct != NULL)
959 {
960+ struct gaih_addrtuple **pat = &at;
961+
962 if (req->ai_family == AF_INET6
963 || req->ai_family == AF_UNSPEC)
964 {
965@@ -917,6 +946,10 @@
966 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
967 break;
968
969+ /* The hosts database does not support MERGE. */
970+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
971+ do_merge = true;
972+
973 if (nip->next == NULL)
974 no_more = -1;
975 else
976@@ -930,7 +969,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
977 }
978
979 process_list:
980- if (at->family == AF_UNSPEC)
981+ if (at == NULL)
982 {
983 result = -EAI_NONAME;
984 goto free_and_return;
985--
9862.39.3
diff --git a/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch b/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch
new file mode 100644
index 0000000000..4d3146509a
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2023-4911.patch
@@ -0,0 +1,63 @@
1From d2b77337f734fcacdfc8e0ddec14cf31a746c7be Mon Sep 17 00:00:00 2001
2From: Siddhesh Poyarekar <siddhesh@redhat.com>
3Date: Mon, 11 Sep 2023 18:53:15 -0400
4Subject: [PATCH v2] tunables: Terminate immediately if end of input is reached
5
6The string parsing routine may end up writing beyond bounds of tunestr
7if the input tunable string is malformed, of the form name=name=val.
8This gets processed twice, first as name=name=val and next as name=val,
9resulting in tunestr being name=name=val:name=val, thus overflowing
10tunestr.
11
12Terminate the parsing loop at the first instance itself so that tunestr
13does not overflow.
14---
15Changes from v1:
16
17- Also null-terminate tunestr before exiting.
18
19 elf/dl-tunables.c | 17 ++++++++++-------
20 1 file changed, 10 insertions(+), 7 deletions(-)
21
22Upstream-Status: Backport [git://sourceware.org/git/glibc.git]
23CVE: CVE-2023-4911
24
25diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
26index 8e7ee9df10..76cf8b9da3 100644
27--- a/elf/dl-tunables.c
28+++ b/elf/dl-tunables.c
29@@ -187,11 +187,7 @@ parse_tunables (char *tunestr, char *valstring)
30 /* If we reach the end of the string before getting a valid name-value
31 pair, bail out. */
32 if (p[len] == '\0')
33- {
34- if (__libc_enable_secure)
35- tunestr[off] = '\0';
36- return;
37- }
38+ break;
39
40 /* We did not find a valid name-value pair before encountering the
41 colon. */
42@@ -251,9 +247,16 @@ parse_tunables (char *tunestr, char *valstring)
43 }
44 }
45
46- if (p[len] != '\0')
47- p += len + 1;
48+ /* We reached the end while processing the tunable string. */
49+ if (p[len] == '\0')
50+ break;
51+
52+ p += len + 1;
53 }
54+
55+ /* Terminate tunestr before we leave. */
56+ if (__libc_enable_secure)
57+ tunestr[off] = '\0';
58 }
59 #endif
60
61--
622.41.0
63
diff --git a/meta/recipes-core/glibc/glibc/check-test-wrapper b/meta/recipes-core/glibc/glibc/check-test-wrapper
index f8e04e02d2..5cc993f718 100644
--- a/meta/recipes-core/glibc/glibc/check-test-wrapper
+++ b/meta/recipes-core/glibc/glibc/check-test-wrapper
@@ -2,6 +2,7 @@
2import sys 2import sys
3import os 3import os
4import subprocess 4import subprocess
5import resource
5 6
6env = os.environ.copy() 7env = os.environ.copy()
7args = sys.argv[1:] 8args = sys.argv[1:]
@@ -44,12 +45,20 @@ if targettype == "user":
44 qemuargs += ["-L", sysroot] 45 qemuargs += ["-L", sysroot]
45 qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))] 46 qemuargs += ["-E", "LD_LIBRARY_PATH={}".format(":".join(libpaths))]
46 command = qemuargs + args 47 command = qemuargs + args
48
49 # We've seen qemu-arm using up all system memory for some glibc
50 # tests e.g. nptl/tst-pthread-timedlock-lockloop
51 # Cap at 8GB since no test should need more than that
52 # (5GB adds 7 failures for qemuarm glibc test run)
53 limit = 8*1024*1024*1024
54 resource.setrlimit(resource.RLIMIT_AS, (limit, limit))
55
47elif targettype == "ssh": 56elif targettype == "ssh":
48 host = os.environ.get("SSH_HOST", None) 57 host = os.environ.get("SSH_HOST", None)
49 user = os.environ.get("SSH_HOST_USER", None) 58 user = os.environ.get("SSH_HOST_USER", None)
50 port = os.environ.get("SSH_HOST_PORT", None) 59 port = os.environ.get("SSH_HOST_PORT", None)
51 60
52 command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"] 61 command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=quiet"]
53 if port: 62 if port:
54 command += ["-p", str(port)] 63 command += ["-p", str(port)]
55 if not host: 64 if not host:
diff --git a/meta/recipes-core/glibc/glibc_2.31.bb b/meta/recipes-core/glibc/glibc_2.31.bb
index b75bbb4196..296c892994 100644
--- a/meta/recipes-core/glibc/glibc_2.31.bb
+++ b/meta/recipes-core/glibc/glibc_2.31.bb
@@ -1,7 +1,40 @@
1require glibc.inc 1require glibc.inc
2require glibc-version.inc 2require glibc-version.inc
3 3
4CVE_CHECK_WHITELIST += "CVE-2020-10029 CVE-2020-6096 CVE-2016-10228 CVE-2020-1751 CVE-2020-1752" 4CVE_CHECK_WHITELIST += "CVE-2020-10029 CVE-2020-6096 CVE-2016-10228 CVE-2020-1751 CVE-2020-1752 \
5 CVE-2021-27645 CVE-2021-3326 CVE-2020-27618 CVE-2020-29562 CVE-2019-25013 \
6 CVE-2022-23218 CVE-2022-23219 \
7"
8
9# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010022
10# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010023
11# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010024
12# Upstream glibc maintainers dispute there is any issue and have no plans to address it further.
13# "this is being treated as a non-security bug and no real threat."
14CVE_CHECK_WHITELIST += "CVE-2019-1010022 CVE-2019-1010023 CVE-2019-1010024"
15
16# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2019-1010025
17# Allows for ASLR bypass so can bypass some hardening, not an exploit in itself, may allow
18# easier access for another. "ASLR bypass itself is not a vulnerability."
19# Potential patch at https://sourceware.org/bugzilla/show_bug.cgi?id=22853
20CVE_CHECK_WHITELIST += "CVE-2019-1010025"
21
22# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-35942
23# The wordexp function in the GNU C Library (aka glibc) through 2.33 may crash
24# or read arbitrary memory in parse_param (in posix/wordexp.c) when called with
25# an untrusted, crafted pattern, potentially resulting in a denial of service
26# or disclosure of information. Patch was backported to 2.31 branch already:
27# https://sourceware.org/git/?p=glibc.git;a=commit;h=4f0a61f75385c9a5879cbe7202042e88f692a3c8
28# which is already included in the dunfell branch of poky:
29# https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?h=dunfell&id=e1e89ff7d75c3d2223f9e3bd875b9b0c5e15836b
30CVE_CHECK_WHITELIST += "CVE-2021-35942"
31
32# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2023-4527
33# This vulnerability was introduced in 2.36 by commit
34# f282cdbe7f436c75864e5640a409a10485e9abb2 resolv: Implement no-aaaa stub resolver option
35# so our version is not yet vulnerable
36# See https://sourceware.org/bugzilla/show_bug.cgi?id=30842
37CVE_CHECK_WHITELIST += "CVE-2023-4527"
5 38
6DEPENDS += "gperf-native bison-native make-native" 39DEPENDS += "gperf-native bison-native make-native"
7 40
@@ -41,9 +74,21 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
41 file://0027-intl-Emit-no-lines-in-bison-generated-files.patch \ 74 file://0027-intl-Emit-no-lines-in-bison-generated-files.patch \
42 file://0028-inject-file-assembly-directives.patch \ 75 file://0028-inject-file-assembly-directives.patch \
43 file://0029-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch \ 76 file://0029-locale-prevent-maybe-uninitialized-errors-with-Os-BZ.patch \
44 file://CVE-2020-29562.patch \
45 file://CVE-2020-29573.patch \ 77 file://CVE-2020-29573.patch \
46 file://CVE-2019-25013.patch \ 78 file://CVE-2021-33574_1.patch \
79 file://CVE-2021-33574_2.patch \
80 file://CVE-2021-38604.patch \
81 file://0030-elf-Refactor_dl_update-slotinfo-to-avoid-use-after-free.patch \
82 file://0031-elf-Fix-data-races-in-pthread_create-and-TLS-access-BZ-19329.patch \
83 file://0032-elf-Use-relaxed-atomics-for-racy-accesses-BZ-19329.patch \
84 file://0033-elf-Add-test-case-for-BZ-19329.patch \
85 file://0034-elf-Fix-DTV-gap-reuse-logic-BZ-27135.patch \
86 file://0035-x86_64-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \
87 file://0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \
88 file://0037-Avoid-deadlock-between-pthread_create-and-ctors.patch \
89 file://CVE-2023-0687.patch \
90 file://CVE-2023-4911.patch \
91 file://CVE-2023-4813.patch \
47 " 92 "
48S = "${WORKDIR}/git" 93S = "${WORKDIR}/git"
49B = "${WORKDIR}/build-${TARGET_SYS}" 94B = "${WORKDIR}/build-${TARGET_SYS}"
diff --git a/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch b/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch
index 52986e61c7..d1835c7a10 100644
--- a/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch
+++ b/meta/recipes-core/glibc/ldconfig-native-2.12.1/ldconfig.patch
@@ -400,7 +400,7 @@ Index: ldconfig-native-2.12.1/ldconfig.c
400 return 0; 400 return 0;
401 } 401 }
402 402
403+#define REPORT_BUGS_TO "mailing list : poky@yoctoproject.org" 403+#define REPORT_BUGS_TO "mailing list : poky@lists.yoctoproject.org"
404 /* Print bug-reporting information in the help message. */ 404 /* Print bug-reporting information in the help message. */
405 static char * 405 static char *
406 more_help (int key, const char *text, void *input) 406 more_help (int key, const char *text, void *input)
diff --git a/meta/recipes-core/ifupdown/files/0001-inet6.defn-Added-1-option-to-dhclient-on-upping-an-i.patch b/meta/recipes-core/ifupdown/files/0001-inet6.defn-Added-1-option-to-dhclient-on-upping-an-i.patch
new file mode 100644
index 0000000000..e374d8ca59
--- /dev/null
+++ b/meta/recipes-core/ifupdown/files/0001-inet6.defn-Added-1-option-to-dhclient-on-upping-an-i.patch
@@ -0,0 +1,65 @@
1From e2263b58d7733835355d7b46c3caa96d911a4717 Mon Sep 17 00:00:00 2001
2From: Simon Schwarz <simon.schwarz@infoteam.de>
3Date: Fri, 6 Nov 2020 08:53:20 +0100
4Subject: [PATCH] inet6.defn: Added -1 option to dhclient on upping an
5 interface
6
7This prevents hangs on startup when no server is available and dhcpv6 is used
8
9Upstream-Status: Pending
10
11Signed-off-by: Simon Schwarz <simon.schwarz@infoteam.de>
12Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
13---
14 inet6.defn | 12 ++++++------
15 1 file changed, 6 insertions(+), 6 deletions(-)
16
17diff --git a/inet6.defn b/inet6.defn
18index 73dce24..25022e3 100644
19--- a/inet6.defn
20+++ b/inet6.defn
21@@ -29,9 +29,9 @@ method auto
22 if (var_set("accept_ra", ifd) && !var_true("accept_ra", ifd))
23 /sbin/ip link set dev %iface% up
24 /lib/ifupdown/wait-for-ll6.sh if (var_true("dhcp", ifd) && execable("/lib/ifupdown/wait-for-ll6.sh"))
25- /sbin/dhclient -6 -v -P -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
26+ /sbin/dhclient -6 -1 -v -P -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
27 if (var_true("dhcp", ifd) && execable("/sbin/dhclient") && var_true("request_prefix", ifd))
28- /sbin/dhclient -6 -v -S -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
29+ /sbin/dhclient -6 -1 -v -S -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
30 elsif (var_true("dhcp", ifd) && execable("/sbin/dhclient"))
31 echo 'No DHCPv6 client software found!' >&2; false \
32 elsif (var_true("dhcp", ifd))
33@@ -154,9 +154,9 @@ method dhcp
34 if (var_set("accept_ra", ifd) && !var_true("accept_ra", ifd))
35 /sbin/ip link set dev %iface% [[address %hwaddress%]] up
36 /lib/ifupdown/wait-for-ll6.sh if (execable("/lib/ifupdown/wait-for-ll6.sh"))
37- /sbin/dhclient -6 -v -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -P -N -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
38+ /sbin/dhclient -6 -1 -v -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -P -N -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
39 if (execable("/sbin/dhclient") && var_true("request_prefix", ifd))
40- /sbin/dhclient -6 -v -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
41+ /sbin/dhclient -6 -1 -v -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
42 elsif (execable("/sbin/dhclient"))
43 echo 'No DHCPv6 client software found!' >&2; false \
44 elsif (1)
45@@ -325,7 +325,7 @@ method dhcp
46
47 up
48 /sbin/ifconfig %iface% [[link %hwaddress%]] up
49- /sbin/dhclient -6 -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
50+ /sbin/dhclient -6 -1 -pf /run/dhclient6.%iface%.pid -lf /var/lib/dhcp/dhclient6.%iface%.leases -I -df /var/lib/dhcp/dhclient.%iface%.leases %iface% \
51 if (execable("/sbin/dhclient"))
52 echo 'No DHCPv6 client software found!' >&2; false \
53 elsif (1)
54@@ -397,7 +397,7 @@ method dhcp
55 up
56 [[Warning: Option hwaddress: %hwaddress% not yet supported]]
57 inetutils-ifconfig --interface %iface% --up
58- /sbin/dhclient -6 -pf /run/dhclient6.%iface///.%.pid -lf /var/lib/dhcp/dhclient6.%iface///.%.leases -I -df /var/lib/dhcp/dhclient.%iface///.%.leases %iface% \
59+ /sbin/dhclient -6 -1 -pf /run/dhclient6.%iface///.%.pid -lf /var/lib/dhcp/dhclient6.%iface///.%.leases -I -df /var/lib/dhcp/dhclient.%iface///.%.leases %iface% \
60 if (execable("/sbin/dhclient"))
61 echo 'No DHCPv6 client software found!' >&2; false \
62 elsif (1)
63--
642.17.1
65
diff --git a/meta/recipes-core/ifupdown/ifupdown_0.8.35.bb b/meta/recipes-core/ifupdown/ifupdown_0.8.35.bb
index 53cb971d33..c3681defdc 100644
--- a/meta/recipes-core/ifupdown/ifupdown_0.8.35.bb
+++ b/meta/recipes-core/ifupdown/ifupdown_0.8.35.bb
@@ -1,4 +1,5 @@
1SUMMARY = "ifupdown: basic ifup and ifdown used by initscripts" 1SUMMARY = "ifupdown: basic ifup and ifdown used by initscripts"
2HOMEPAGE = "https://salsa.debian.org/debian/ifupdown"
2DESCRIPTION = "High level tools to configure network interfaces \ 3DESCRIPTION = "High level tools to configure network interfaces \
3This package provides the tools ifup and ifdown which may be used to \ 4This package provides the tools ifup and ifdown which may be used to \
4configure (or, respectively, deconfigure) network interfaces, based on \ 5configure (or, respectively, deconfigure) network interfaces, based on \
@@ -6,11 +7,12 @@ the file /etc/network/interfaces."
6LICENSE = "GPLv2" 7LICENSE = "GPLv2"
7LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" 8LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f"
8 9
9SRC_URI = "git://salsa.debian.org/debian/ifupdown.git;protocol=https \ 10SRC_URI = "git://salsa.debian.org/debian/ifupdown.git;protocol=https;branch=master \
10 file://defn2-c-man-don-t-rely-on-dpkg-architecture-to-set-a.patch \ 11 file://defn2-c-man-don-t-rely-on-dpkg-architecture-to-set-a.patch \
11 file://99_network \ 12 file://99_network \
12 file://0001-Define-FNM_EXTMATCH-for-musl.patch \ 13 file://0001-Define-FNM_EXTMATCH-for-musl.patch \
13 file://0001-Makefile-do-not-use-dpkg-for-determining-OS-type.patch \ 14 file://0001-Makefile-do-not-use-dpkg-for-determining-OS-type.patch \
15 file://0001-inet6.defn-Added-1-option-to-dhclient-on-upping-an-i.patch \
14 file://run-ptest \ 16 file://run-ptest \
15 ${@bb.utils.contains('DISTRO_FEATURES', 'ptest', 'file://tweak-ptest-script.patch', '', d)} \ 17 ${@bb.utils.contains('DISTRO_FEATURES', 'ptest', 'file://tweak-ptest-script.patch', '', d)} \
16 " 18 "
diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
index f5cc20fa6d..035312f4d9 100644
--- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb
+++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
@@ -22,9 +22,9 @@ APPEND += "rootfstype=ext4 quiet"
22DEPENDS = "zip-native python3-pip-native" 22DEPENDS = "zip-native python3-pip-native"
23IMAGE_FSTYPES = "wic.vmdk" 23IMAGE_FSTYPES = "wic.vmdk"
24 24
25inherit core-image module-base setuptools3 25inherit core-image setuptools3
26 26
27SRCREV ?= "fadf7d3343305337c38a5243797723c68e88276a" 27SRCREV ?= "77442211926cbe93d60108f6df4abda3bc06b735"
28SRC_URI = "git://git.yoctoproject.org/poky;branch=dunfell \ 28SRC_URI = "git://git.yoctoproject.org/poky;branch=dunfell \
29 file://Yocto_Build_Appliance.vmx \ 29 file://Yocto_Build_Appliance.vmx \
30 file://Yocto_Build_Appliance.vmxf \ 30 file://Yocto_Build_Appliance.vmxf \
@@ -61,12 +61,6 @@ fakeroot do_populate_poky_src () {
61 # Place the README_VirtualBox_Toaster file in builders home folder. 61 # Place the README_VirtualBox_Toaster file in builders home folder.
62 cp ${WORKDIR}/README_VirtualBox_Toaster.txt ${IMAGE_ROOTFS}/home/builder/ 62 cp ${WORKDIR}/README_VirtualBox_Toaster.txt ${IMAGE_ROOTFS}/home/builder/
63 63
64 # Create a symlink, needed for out-of-tree kernel modules build
65 if [ ! -e ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build ]; then
66 rm -f ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build
67 lnr ${IMAGE_ROOTFS}${KERNEL_SRC_PATH} ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build
68 fi
69
70 echo "INHERIT += \"rm_work\"" >> ${IMAGE_ROOTFS}/home/builder/poky/build/conf/auto.conf 64 echo "INHERIT += \"rm_work\"" >> ${IMAGE_ROOTFS}/home/builder/poky/build/conf/auto.conf
71 echo "export LC_ALL=en_US.utf8" >> ${IMAGE_ROOTFS}/home/builder/.bashrc 65 echo "export LC_ALL=en_US.utf8" >> ${IMAGE_ROOTFS}/home/builder/.bashrc
72 66
diff --git a/meta/recipes-core/initrdscripts/files/init-install-efi.sh b/meta/recipes-core/initrdscripts/files/init-install-efi.sh
index b6855b5aac..f667518b89 100644
--- a/meta/recipes-core/initrdscripts/files/init-install-efi.sh
+++ b/meta/recipes-core/initrdscripts/files/init-install-efi.sh
@@ -279,6 +279,11 @@ fi
279 279
280umount /tgt_root 280umount /tgt_root
281 281
282# copy any extra files needed for ESP
283if [ -d /run/media/$1/esp ]; then
284 cp -r /run/media/$1/esp/* /boot
285fi
286
282# Copy kernel artifacts. To add more artifacts just add to types 287# Copy kernel artifacts. To add more artifacts just add to types
283# For now just support kernel types already being used by something in OE-core 288# For now just support kernel types already being used by something in OE-core
284for types in bzImage zImage vmlinux vmlinuz fitImage; do 289for types in bzImage zImage vmlinux vmlinuz fitImage; do
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/finish b/meta/recipes-core/initrdscripts/initramfs-framework/finish
index 717383ebac..dee3ab3387 100755
--- a/meta/recipes-core/initrdscripts/initramfs-framework/finish
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/finish
@@ -14,6 +14,15 @@ finish_run() {
14 14
15 info "Switching root to '$ROOTFS_DIR'..." 15 info "Switching root to '$ROOTFS_DIR'..."
16 16
17 debug "Moving basic mounts onto rootfs"
18 for dir in `awk '/\/dev.* \/run\/media/{print $2}' /proc/mounts`; do
19 # Parse any OCT or HEX encoded chars such as spaces
20 # in the mount points to actual ASCII chars
21 dir=`printf $dir`
22 mkdir -p "${ROOTFS_DIR}/media/${dir##*/}"
23 mount -n --move "$dir" "${ROOTFS_DIR}/media/${dir##*/}"
24 done
25
17 debug "Moving /dev, /proc and /sys onto rootfs..." 26 debug "Moving /dev, /proc and /sys onto rootfs..."
18 mount --move /dev $ROOTFS_DIR/dev 27 mount --move /dev $ROOTFS_DIR/dev
19 mount --move /proc $ROOTFS_DIR/proc 28 mount --move /proc $ROOTFS_DIR/proc
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/rootfs b/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
index 748c9391c0..1d8a0ae66d 100644
--- a/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
@@ -67,8 +67,8 @@ rootfs_run() {
67 # It is unlikely to change, but keep trying anyway. 67 # It is unlikely to change, but keep trying anyway.
68 # Perhaps we pick a different device next time. 68 # Perhaps we pick a different device next time.
69 umount $ROOTFS_DIR 69 umount $ROOTFS_DIR
70 fi
71 fi 70 fi
71 fi
72 fi 72 fi
73 debug "Sleeping for $delay second(s) to wait root to settle..." 73 debug "Sleeping for $delay second(s) to wait root to settle..."
74 sleep $delay 74 sleep $delay
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/setup-live b/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
index 4c79f41285..7e92f93322 100644
--- a/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
@@ -1,4 +1,4 @@
1#/bin/sh 1#!/bin/sh
2# Copyright (C) 2011 O.S. Systems Software LTDA. 2# Copyright (C) 2011 O.S. Systems Software LTDA.
3# Licensed on MIT 3# Licensed on MIT
4 4
diff --git a/meta/recipes-core/initscripts/initscripts_1.0.bb b/meta/recipes-core/initscripts/initscripts_1.0.bb
index f98e42eb2e..cb5417cc39 100644
--- a/meta/recipes-core/initscripts/initscripts_1.0.bb
+++ b/meta/recipes-core/initscripts/initscripts_1.0.bb
@@ -129,7 +129,7 @@ do_install () {
129 update-rc.d -r ${D} rmnologin.sh start 99 2 3 4 5 . 129 update-rc.d -r ${D} rmnologin.sh start 99 2 3 4 5 .
130 update-rc.d -r ${D} sendsigs start 20 0 6 . 130 update-rc.d -r ${D} sendsigs start 20 0 6 .
131 update-rc.d -r ${D} urandom start 38 S 0 6 . 131 update-rc.d -r ${D} urandom start 38 S 0 6 .
132 update-rc.d -r ${D} umountnfs.sh start 31 0 1 6 . 132 update-rc.d -r ${D} umountnfs.sh stop 31 0 1 6 .
133 update-rc.d -r ${D} umountfs start 40 0 6 . 133 update-rc.d -r ${D} umountfs start 40 0 6 .
134 update-rc.d -r ${D} reboot start 90 6 . 134 update-rc.d -r ${D} reboot start 90 6 .
135 update-rc.d -r ${D} halt start 90 0 . 135 update-rc.d -r ${D} halt start 90 0 .
diff --git a/meta/recipes-core/kbd/kbd_2.2.0.bb b/meta/recipes-core/kbd/kbd_2.2.0.bb
index e5700ff57f..d10c93dfb7 100644
--- a/meta/recipes-core/kbd/kbd_2.2.0.bb
+++ b/meta/recipes-core/kbd/kbd_2.2.0.bb
@@ -1,5 +1,6 @@
1SUMMARY = "Keytable files and keyboard utilities" 1SUMMARY = "Keytable files and keyboard utilities"
2HOMEPAGE = "http://www.kbd-project.org/" 2HOMEPAGE = "http://www.kbd-project.org/"
3DESCRIPTION = "The kbd project contains tools for managing Linux console (Linux console, virtual terminals, keyboard, etc.) – mainly, what they do is loading console fonts and keyboard maps."
3# everything minus console-fonts is GPLv2+ 4# everything minus console-fonts is GPLv2+
4LICENSE = "GPLv2+" 5LICENSE = "GPLv2+"
5LIC_FILES_CHKSUM = "file://COPYING;md5=892f569a555ba9c07a568a7c0c4fa63a" 6LIC_FILES_CHKSUM = "file://COPYING;md5=892f569a555ba9c07a568a7c0c4fa63a"
diff --git a/meta/recipes-core/libxcrypt/libxcrypt.inc b/meta/recipes-core/libxcrypt/libxcrypt.inc
index 2d2a0b03e3..b6bf48ba79 100644
--- a/meta/recipes-core/libxcrypt/libxcrypt.inc
+++ b/meta/recipes-core/libxcrypt/libxcrypt.inc
@@ -9,7 +9,7 @@ LIC_FILES_CHKSUM ?= "file://LICENSING;md5=3bb6614cf5880cbf1b9dbd9e3d145e2c \
9 9
10inherit autotools pkgconfig 10inherit autotools pkgconfig
11 11
12SRC_URI = "git://github.com/besser82/libxcrypt.git;branch=${SRCBRANCH}" 12SRC_URI = "git://github.com/besser82/libxcrypt.git;branch=${SRCBRANCH};protocol=https"
13SRCREV = "823437d015cd4ab4d100ed205f218681b03ae45c" 13SRCREV = "823437d015cd4ab4d100ed205f218681b03ae45c"
14SRCBRANCH ?= "develop" 14SRCBRANCH ?= "develop"
15 15
diff --git a/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch b/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch
new file mode 100644
index 0000000000..b0d26d1c08
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/0001-Port-gentest.py-to-Python-3.patch
@@ -0,0 +1,813 @@
1From b5125000917810731bc28055c0445d571121f80e Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Thu, 21 Apr 2022 00:45:58 +0200
4Subject: [PATCH] Port gentest.py to Python 3
5
6Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/343fc1421cdae097fa6c4cffeb1a065a40be6bbb]
7
8* fixes:
9
10make[1]: 'testReader' is up to date.
11 File "../libxml2-2.9.10/gentest.py", line 11
12 print "libxml2 python bindings not available, skipping testapi.c generation"
13 ^
14SyntaxError: Missing parentheses in call to 'print'. Did you mean print("libxml2 python bindings not available, skipping testapi.c generation")?
15make[1]: [Makefile:2078: testapi.c] Error 1 (ignored)
16
17...
18
19make[1]: 'testReader' is up to date.
20 File "../libxml2-2.9.10/gentest.py", line 271
21 return 1
22 ^
23TabError: inconsistent use of tabs and spaces in indentation
24make[1]: [Makefile:2078: testapi.c] Error 1 (ignored)
25
26...
27
28aarch64-oe-linux-gcc: error: testapi.c: No such file or directory
29aarch64-oe-linux-gcc: fatal error: no input files
30compilation terminated.
31make[1]: *** [Makefile:1275: testapi.o] Error 1
32
33But there is still a bit mystery why it worked before, because check-am
34calls gentest.py with $(PYTHON), so it ignores the shebang in the script
35and libxml2 is using python3native (through python3targetconfig.bbclass)
36so something like:
37
38libxml2/2.9.10-r0/recipe-sysroot-native/usr/bin/python3-native/python3 gentest.py
39
40But that still fails (now without SyntaxError) with:
41libxml2 python bindings not available, skipping testapi.c generation
42
43because we don't have dependency on libxml2-native (to provide libxml2
44python bindings form python3native) and exported PYTHON_SITE_PACKAGES
45might be useless (e.g. /usr/lib/python3.8/site-packages on Ubuntu-22.10
46which uses python 3.10 and there is no site-packages with libxml2)
47
48Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
49---
50 gentest.py | 421 ++++++++++++++++++++++++++---------------------------
51 1 file changed, 209 insertions(+), 212 deletions(-)
52
53diff --git a/gentest.py b/gentest.py
54index b763300..0756706 100755
55--- a/gentest.py
56+++ b/gentest.py
57@@ -8,7 +8,7 @@ import string
58 try:
59 import libxml2
60 except:
61- print "libxml2 python bindings not available, skipping testapi.c generation"
62+ print("libxml2 python bindings not available, skipping testapi.c generation")
63 sys.exit(0)
64
65 if len(sys.argv) > 1:
66@@ -227,7 +227,7 @@ extra_post_call = {
67 if (old != NULL) {
68 xmlUnlinkNode(old);
69 xmlFreeNode(old) ; old = NULL ; }
70- ret_val = NULL;""",
71+\t ret_val = NULL;""",
72 "xmlTextMerge":
73 """if ((first != NULL) && (first->type != XML_TEXT_NODE)) {
74 xmlUnlinkNode(second);
75@@ -236,7 +236,7 @@ extra_post_call = {
76 """if ((ret_val != NULL) && (ret_val != ncname) &&
77 (ret_val != prefix) && (ret_val != memory))
78 xmlFree(ret_val);
79- ret_val = NULL;""",
80+\t ret_val = NULL;""",
81 "xmlNewDocElementContent":
82 """xmlFreeDocElementContent(doc, ret_val); ret_val = NULL;""",
83 "xmlDictReference": "xmlDictFree(dict);",
84@@ -268,29 +268,29 @@ modules = []
85 def is_skipped_module(name):
86 for mod in skipped_modules:
87 if mod == name:
88- return 1
89+ return 1
90 return 0
91
92 def is_skipped_function(name):
93 for fun in skipped_functions:
94 if fun == name:
95- return 1
96+ return 1
97 # Do not test destructors
98- if string.find(name, 'Free') != -1:
99+ if name.find('Free') != -1:
100 return 1
101 return 0
102
103 def is_skipped_memcheck(name):
104 for fun in skipped_memcheck:
105 if fun == name:
106- return 1
107+ return 1
108 return 0
109
110 missing_types = {}
111 def add_missing_type(name, func):
112 try:
113 list = missing_types[name]
114- list.append(func)
115+ list.append(func)
116 except:
117 missing_types[name] = [func]
118
119@@ -310,7 +310,7 @@ def add_missing_functions(name, module):
120 missing_functions_nr = missing_functions_nr + 1
121 try:
122 list = missing_functions[module]
123- list.append(name)
124+ list.append(name)
125 except:
126 missing_functions[module] = [name]
127
128@@ -319,45 +319,45 @@ def add_missing_functions(name, module):
129 #
130
131 def type_convert(str, name, info, module, function, pos):
132-# res = string.replace(str, " ", " ")
133-# res = string.replace(str, " ", " ")
134-# res = string.replace(str, " ", " ")
135- res = string.replace(str, " *", "_ptr")
136-# res = string.replace(str, "*", "_ptr")
137- res = string.replace(res, " ", "_")
138+# res = str.replace(" ", " ")
139+# res = str.replace(" ", " ")
140+# res = str.replace(" ", " ")
141+ res = str.replace(" *", "_ptr")
142+# res = str.replace("*", "_ptr")
143+ res = res.replace(" ", "_")
144 if res == 'const_char_ptr':
145- if string.find(name, "file") != -1 or \
146- string.find(name, "uri") != -1 or \
147- string.find(name, "URI") != -1 or \
148- string.find(info, "filename") != -1 or \
149- string.find(info, "URI") != -1 or \
150- string.find(info, "URL") != -1:
151- if string.find(function, "Save") != -1 or \
152- string.find(function, "Create") != -1 or \
153- string.find(function, "Write") != -1 or \
154- string.find(function, "Fetch") != -1:
155- return('fileoutput')
156- return('filepath')
157+ if name.find("file") != -1 or \
158+ name.find("uri") != -1 or \
159+ name.find("URI") != -1 or \
160+ info.find("filename") != -1 or \
161+ info.find("URI") != -1 or \
162+ info.find("URL") != -1:
163+ if function.find("Save") != -1 or \
164+ function.find("Create") != -1 or \
165+ function.find("Write") != -1 or \
166+ function.find("Fetch") != -1:
167+ return('fileoutput')
168+ return('filepath')
169 if res == 'void_ptr':
170 if module == 'nanoftp' and name == 'ctx':
171- return('xmlNanoFTPCtxtPtr')
172+ return('xmlNanoFTPCtxtPtr')
173 if function == 'xmlNanoFTPNewCtxt' or \
174- function == 'xmlNanoFTPConnectTo' or \
175- function == 'xmlNanoFTPOpen':
176- return('xmlNanoFTPCtxtPtr')
177+ function == 'xmlNanoFTPConnectTo' or \
178+ function == 'xmlNanoFTPOpen':
179+ return('xmlNanoFTPCtxtPtr')
180 if module == 'nanohttp' and name == 'ctx':
181- return('xmlNanoHTTPCtxtPtr')
182- if function == 'xmlNanoHTTPMethod' or \
183- function == 'xmlNanoHTTPMethodRedir' or \
184- function == 'xmlNanoHTTPOpen' or \
185- function == 'xmlNanoHTTPOpenRedir':
186- return('xmlNanoHTTPCtxtPtr');
187+ return('xmlNanoHTTPCtxtPtr')
188+ if function == 'xmlNanoHTTPMethod' or \
189+ function == 'xmlNanoHTTPMethodRedir' or \
190+ function == 'xmlNanoHTTPOpen' or \
191+ function == 'xmlNanoHTTPOpenRedir':
192+ return('xmlNanoHTTPCtxtPtr');
193 if function == 'xmlIOHTTPOpen':
194- return('xmlNanoHTTPCtxtPtr')
195- if string.find(name, "data") != -1:
196- return('userdata')
197- if string.find(name, "user") != -1:
198- return('userdata')
199+ return('xmlNanoHTTPCtxtPtr')
200+ if name.find("data") != -1:
201+ return('userdata')
202+ if name.find("user") != -1:
203+ return('userdata')
204 if res == 'xmlDoc_ptr':
205 res = 'xmlDocPtr'
206 if res == 'xmlNode_ptr':
207@@ -366,18 +366,18 @@ def type_convert(str, name, info, module, function, pos):
208 res = 'xmlDictPtr'
209 if res == 'xmlNodePtr' and pos != 0:
210 if (function == 'xmlAddChild' and pos == 2) or \
211- (function == 'xmlAddChildList' and pos == 2) or \
212+ (function == 'xmlAddChildList' and pos == 2) or \
213 (function == 'xmlAddNextSibling' and pos == 2) or \
214 (function == 'xmlAddSibling' and pos == 2) or \
215 (function == 'xmlDocSetRootElement' and pos == 2) or \
216 (function == 'xmlReplaceNode' and pos == 2) or \
217 (function == 'xmlTextMerge') or \
218- (function == 'xmlAddPrevSibling' and pos == 2):
219- return('xmlNodePtr_in');
220+ (function == 'xmlAddPrevSibling' and pos == 2):
221+ return('xmlNodePtr_in');
222 if res == 'const xmlBufferPtr':
223 res = 'xmlBufferPtr'
224 if res == 'xmlChar_ptr' and name == 'name' and \
225- string.find(function, "EatName") != -1:
226+ function.find("EatName") != -1:
227 return('eaten_name')
228 if res == 'void_ptr*':
229 res = 'void_ptr_ptr'
230@@ -393,7 +393,7 @@ def type_convert(str, name, info, module, function, pos):
231 res = 'debug_FILE_ptr';
232 if res == 'int' and name == 'options':
233 if module == 'parser' or module == 'xmlreader':
234- res = 'parseroptions'
235+ res = 'parseroptions'
236
237 return res
238
239@@ -402,28 +402,28 @@ known_param_types = []
240 def is_known_param_type(name):
241 for type in known_param_types:
242 if type == name:
243- return 1
244+ return 1
245 return name[-3:] == 'Ptr' or name[-4:] == '_ptr'
246
247 def generate_param_type(name, rtype):
248 global test
249 for type in known_param_types:
250 if type == name:
251- return
252+ return
253 for type in generated_param_types:
254 if type == name:
255- return
256+ return
257
258 if name[-3:] == 'Ptr' or name[-4:] == '_ptr':
259 if rtype[0:6] == 'const ':
260- crtype = rtype[6:]
261- else:
262- crtype = rtype
263+ crtype = rtype[6:]
264+ else:
265+ crtype = rtype
266
267 define = 0
268- if modules_defines.has_key(module):
269- test.write("#ifdef %s\n" % (modules_defines[module]))
270- define = 1
271+ if module in modules_defines:
272+ test.write("#ifdef %s\n" % (modules_defines[module]))
273+ define = 1
274 test.write("""
275 #define gen_nb_%s 1
276 static %s gen_%s(int no ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
277@@ -433,7 +433,7 @@ static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTR
278 }
279 """ % (name, crtype, name, name, rtype))
280 if define == 1:
281- test.write("#endif\n\n")
282+ test.write("#endif\n\n")
283 add_generated_param_type(name)
284
285 #
286@@ -445,7 +445,7 @@ known_return_types = []
287 def is_known_return_type(name):
288 for type in known_return_types:
289 if type == name:
290- return 1
291+ return 1
292 return 0
293
294 #
295@@ -471,7 +471,7 @@ def compare_and_save():
296 try:
297 os.system("rm testapi.c; mv testapi.c.new testapi.c")
298 except:
299- os.system("mv testapi.c.new testapi.c")
300+ os.system("mv testapi.c.new testapi.c")
301 print("Updated testapi.c")
302 else:
303 print("Generated testapi.c is identical")
304@@ -481,17 +481,17 @@ while line != "":
305 if line == "/* CUT HERE: everything below that line is generated */\n":
306 break;
307 if line[0:15] == "#define gen_nb_":
308- type = string.split(line[15:])[0]
309- known_param_types.append(type)
310+ type = line[15:].split()[0]
311+ known_param_types.append(type)
312 if line[0:19] == "static void desret_":
313- type = string.split(line[19:], '(')[0]
314- known_return_types.append(type)
315+ type = line[19:].split('(')[0]
316+ known_return_types.append(type)
317 test.write(line)
318 line = input.readline()
319 input.close()
320
321 if line == "":
322- print "Could not find the CUT marker in testapi.c skipping generation"
323+ print("Could not find the CUT marker in testapi.c skipping generation")
324 test.close()
325 sys.exit(0)
326
327@@ -505,7 +505,7 @@ test.write("/* CUT HERE: everything below that line is generated */\n")
328 #
329 doc = libxml2.readFile(srcPref + 'doc/libxml2-api.xml', None, 0)
330 if doc == None:
331- print "Failed to load doc/libxml2-api.xml"
332+ print("Failed to load doc/libxml2-api.xml")
333 sys.exit(1)
334 ctxt = doc.xpathNewContext()
335
336@@ -519,9 +519,9 @@ for arg in args:
337 mod = arg.xpathEval('string(../@file)')
338 func = arg.xpathEval('string(../@name)')
339 if (mod not in skipped_modules) and (func not in skipped_functions):
340- type = arg.xpathEval('string(@type)')
341- if not argtypes.has_key(type):
342- argtypes[type] = func
343+ type = arg.xpathEval('string(@type)')
344+ if type not in argtypes:
345+ argtypes[type] = func
346
347 # similarly for return types
348 rettypes = {}
349@@ -531,8 +531,8 @@ for ret in rets:
350 func = ret.xpathEval('string(../@name)')
351 if (mod not in skipped_modules) and (func not in skipped_functions):
352 type = ret.xpathEval('string(@type)')
353- if not rettypes.has_key(type):
354- rettypes[type] = func
355+ if type not in rettypes:
356+ rettypes[type] = func
357
358 #
359 # Generate constructors and return type handling for all enums
360@@ -549,49 +549,49 @@ for enum in enums:
361 continue;
362 define = 0
363
364- if argtypes.has_key(name) and is_known_param_type(name) == 0:
365- values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
366- i = 0
367- vals = []
368- for value in values:
369- vname = value.xpathEval('string(@name)')
370- if vname == None:
371- continue;
372- i = i + 1
373- if i >= 5:
374- break;
375- vals.append(vname)
376- if vals == []:
377- print "Didn't find any value for enum %s" % (name)
378- continue
379- if modules_defines.has_key(module):
380- test.write("#ifdef %s\n" % (modules_defines[module]))
381- define = 1
382- test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
383- test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
384- (name, name))
385- i = 1
386- for value in vals:
387- test.write(" if (no == %d) return(%s);\n" % (i, value))
388- i = i + 1
389- test.write(""" return(0);
390+ if (name in argtypes) and is_known_param_type(name) == 0:
391+ values = ctxt.xpathEval("/api/symbols/enum[@type='%s']" % name)
392+ i = 0
393+ vals = []
394+ for value in values:
395+ vname = value.xpathEval('string(@name)')
396+ if vname == None:
397+ continue;
398+ i = i + 1
399+ if i >= 5:
400+ break;
401+ vals.append(vname)
402+ if vals == []:
403+ print("Didn't find any value for enum %s" % (name))
404+ continue
405+ if module in modules_defines:
406+ test.write("#ifdef %s\n" % (modules_defines[module]))
407+ define = 1
408+ test.write("#define gen_nb_%s %d\n" % (name, len(vals)))
409+ test.write("""static %s gen_%s(int no, int nr ATTRIBUTE_UNUSED) {\n""" %
410+ (name, name))
411+ i = 1
412+ for value in vals:
413+ test.write(" if (no == %d) return(%s);\n" % (i, value))
414+ i = i + 1
415+ test.write(""" return(0);
416 }
417
418 static void des_%s(int no ATTRIBUTE_UNUSED, %s val ATTRIBUTE_UNUSED, int nr ATTRIBUTE_UNUSED) {
419 }
420
421 """ % (name, name));
422- known_param_types.append(name)
423+ known_param_types.append(name)
424
425 if (is_known_return_type(name) == 0) and (name in rettypes):
426- if define == 0 and modules_defines.has_key(module):
427- test.write("#ifdef %s\n" % (modules_defines[module]))
428- define = 1
429+ if define == 0 and (module in modules_defines):
430+ test.write("#ifdef %s\n" % (modules_defines[module]))
431+ define = 1
432 test.write("""static void desret_%s(%s val ATTRIBUTE_UNUSED) {
433 }
434
435 """ % (name, name))
436- known_return_types.append(name)
437+ known_return_types.append(name)
438 if define == 1:
439 test.write("#endif\n\n")
440
441@@ -615,9 +615,9 @@ for file in headers:
442 # do not test deprecated APIs
443 #
444 desc = file.xpathEval('string(description)')
445- if string.find(desc, 'DEPRECATED') != -1:
446- print "Skipping deprecated interface %s" % name
447- continue;
448+ if desc.find('DEPRECATED') != -1:
449+ print("Skipping deprecated interface %s" % name)
450+ continue;
451
452 test.write("#include <libxml/%s.h>\n" % name)
453 modules.append(name)
454@@ -679,7 +679,7 @@ def generate_test(module, node):
455 # and store the informations for the generation
456 #
457 try:
458- args = node.xpathEval("arg")
459+ args = node.xpathEval("arg")
460 except:
461 args = []
462 t_args = []
463@@ -687,37 +687,37 @@ def generate_test(module, node):
464 for arg in args:
465 n = n + 1
466 rtype = arg.xpathEval("string(@type)")
467- if rtype == 'void':
468- break;
469- info = arg.xpathEval("string(@info)")
470- nam = arg.xpathEval("string(@name)")
471+ if rtype == 'void':
472+ break;
473+ info = arg.xpathEval("string(@info)")
474+ nam = arg.xpathEval("string(@name)")
475 type = type_convert(rtype, nam, info, module, name, n)
476- if is_known_param_type(type) == 0:
477- add_missing_type(type, name);
478- no_gen = 1
479+ if is_known_param_type(type) == 0:
480+ add_missing_type(type, name);
481+ no_gen = 1
482 if (type[-3:] == 'Ptr' or type[-4:] == '_ptr') and \
483- rtype[0:6] == 'const ':
484- crtype = rtype[6:]
485- else:
486- crtype = rtype
487- t_args.append((nam, type, rtype, crtype, info))
488+ rtype[0:6] == 'const ':
489+ crtype = rtype[6:]
490+ else:
491+ crtype = rtype
492+ t_args.append((nam, type, rtype, crtype, info))
493
494 try:
495- rets = node.xpathEval("return")
496+ rets = node.xpathEval("return")
497 except:
498 rets = []
499 t_ret = None
500 for ret in rets:
501 rtype = ret.xpathEval("string(@type)")
502- info = ret.xpathEval("string(@info)")
503+ info = ret.xpathEval("string(@info)")
504 type = type_convert(rtype, 'return', info, module, name, 0)
505- if rtype == 'void':
506- break
507- if is_known_return_type(type) == 0:
508- add_missing_type(type, name);
509- no_gen = 1
510- t_ret = (type, rtype, info)
511- break
512+ if rtype == 'void':
513+ break
514+ if is_known_return_type(type) == 0:
515+ add_missing_type(type, name);
516+ no_gen = 1
517+ t_ret = (type, rtype, info)
518+ break
519
520 if no_gen == 0:
521 for t_arg in t_args:
522@@ -733,7 +733,7 @@ test_%s(void) {
523
524 if no_gen == 1:
525 add_missing_functions(name, module)
526- test.write("""
527+ test.write("""
528 /* missing type support */
529 return(test_ret);
530 }
531@@ -742,22 +742,22 @@ test_%s(void) {
532 return
533
534 try:
535- conds = node.xpathEval("cond")
536- for cond in conds:
537- test.write("#if %s\n" % (cond.get_content()))
538- nb_cond = nb_cond + 1
539+ conds = node.xpathEval("cond")
540+ for cond in conds:
541+ test.write("#if %s\n" % (cond.get_content()))
542+ nb_cond = nb_cond + 1
543 except:
544 pass
545
546 define = 0
547- if function_defines.has_key(name):
548+ if name in function_defines:
549 test.write("#ifdef %s\n" % (function_defines[name]))
550- define = 1
551+ define = 1
552
553 # Declare the memory usage counter
554 no_mem = is_skipped_memcheck(name)
555 if no_mem == 0:
556- test.write(" int mem_base;\n");
557+ test.write(" int mem_base;\n");
558
559 # Declare the return value
560 if t_ret != None:
561@@ -766,29 +766,29 @@ test_%s(void) {
562 # Declare the arguments
563 for arg in t_args:
564 (nam, type, rtype, crtype, info) = arg;
565- # add declaration
566- test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
567- test.write(" int n_%s;\n" % (nam))
568+ # add declaration
569+ test.write(" %s %s; /* %s */\n" % (crtype, nam, info))
570+ test.write(" int n_%s;\n" % (nam))
571 test.write("\n")
572
573 # Cascade loop on of each argument list of values
574 for arg in t_args:
575 (nam, type, rtype, crtype, info) = arg;
576- #
577- test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
578- nam, nam, type, nam))
579+ #
580+ test.write(" for (n_%s = 0;n_%s < gen_nb_%s;n_%s++) {\n" % (
581+ nam, nam, type, nam))
582
583 # log the memory usage
584 if no_mem == 0:
585- test.write(" mem_base = xmlMemBlocks();\n");
586+ test.write(" mem_base = xmlMemBlocks();\n");
587
588 # prepare the call
589 i = 0;
590 for arg in t_args:
591 (nam, type, rtype, crtype, info) = arg;
592- #
593- test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
594- i = i + 1;
595+ #
596+ test.write(" %s = gen_%s(n_%s, %d);\n" % (nam, type, nam, i))
597+ i = i + 1;
598
599 # add checks to avoid out-of-bounds array access
600 i = 0;
601@@ -797,7 +797,7 @@ test_%s(void) {
602 # assume that "size", "len", and "start" parameters apply to either
603 # the nearest preceding or following char pointer
604 if type == "int" and (nam == "size" or nam == "len" or nam == "start"):
605- for j in range(i - 1, -1, -1) + range(i + 1, len(t_args)):
606+ for j in (*range(i - 1, -1, -1), *range(i + 1, len(t_args))):
607 (bnam, btype) = t_args[j][:2]
608 if btype == "const_char_ptr" or btype == "const_xmlChar_ptr":
609 test.write(
610@@ -806,42 +806,42 @@ test_%s(void) {
611 " continue;\n"
612 % (bnam, nam, bnam))
613 break
614- i = i + 1;
615+ i = i + 1;
616
617 # do the call, and clanup the result
618- if extra_pre_call.has_key(name):
619- test.write(" %s\n"% (extra_pre_call[name]))
620+ if name in extra_pre_call:
621+ test.write(" %s\n"% (extra_pre_call[name]))
622 if t_ret != None:
623- test.write("\n ret_val = %s(" % (name))
624- need = 0
625- for arg in t_args:
626- (nam, type, rtype, crtype, info) = arg
627- if need:
628- test.write(", ")
629- else:
630- need = 1
631- if rtype != crtype:
632- test.write("(%s)" % rtype)
633- test.write("%s" % nam);
634- test.write(");\n")
635- if extra_post_call.has_key(name):
636- test.write(" %s\n"% (extra_post_call[name]))
637- test.write(" desret_%s(ret_val);\n" % t_ret[0])
638+ test.write("\n ret_val = %s(" % (name))
639+ need = 0
640+ for arg in t_args:
641+ (nam, type, rtype, crtype, info) = arg
642+ if need:
643+ test.write(", ")
644+ else:
645+ need = 1
646+ if rtype != crtype:
647+ test.write("(%s)" % rtype)
648+ test.write("%s" % nam);
649+ test.write(");\n")
650+ if name in extra_post_call:
651+ test.write(" %s\n"% (extra_post_call[name]))
652+ test.write(" desret_%s(ret_val);\n" % t_ret[0])
653 else:
654- test.write("\n %s(" % (name));
655- need = 0;
656- for arg in t_args:
657- (nam, type, rtype, crtype, info) = arg;
658- if need:
659- test.write(", ")
660- else:
661- need = 1
662- if rtype != crtype:
663- test.write("(%s)" % rtype)
664- test.write("%s" % nam)
665- test.write(");\n")
666- if extra_post_call.has_key(name):
667- test.write(" %s\n"% (extra_post_call[name]))
668+ test.write("\n %s(" % (name));
669+ need = 0;
670+ for arg in t_args:
671+ (nam, type, rtype, crtype, info) = arg;
672+ if need:
673+ test.write(", ")
674+ else:
675+ need = 1
676+ if rtype != crtype:
677+ test.write("(%s)" % rtype)
678+ test.write("%s" % nam)
679+ test.write(");\n")
680+ if name in extra_post_call:
681+ test.write(" %s\n"% (extra_post_call[name]))
682
683 test.write(" call_tests++;\n");
684
685@@ -849,32 +849,32 @@ test_%s(void) {
686 i = 0;
687 for arg in t_args:
688 (nam, type, rtype, crtype, info) = arg;
689- # This is a hack to prevent generating a destructor for the
690- # 'input' argument in xmlTextReaderSetup. There should be
691- # a better, more generic way to do this!
692- if string.find(info, 'destroy') == -1:
693- test.write(" des_%s(n_%s, " % (type, nam))
694- if rtype != crtype:
695- test.write("(%s)" % rtype)
696- test.write("%s, %d);\n" % (nam, i))
697- i = i + 1;
698+ # This is a hack to prevent generating a destructor for the
699+ # 'input' argument in xmlTextReaderSetup. There should be
700+ # a better, more generic way to do this!
701+ if info.find('destroy') == -1:
702+ test.write(" des_%s(n_%s, " % (type, nam))
703+ if rtype != crtype:
704+ test.write("(%s)" % rtype)
705+ test.write("%s, %d);\n" % (nam, i))
706+ i = i + 1;
707
708 test.write(" xmlResetLastError();\n");
709 # Check the memory usage
710 if no_mem == 0:
711- test.write(""" if (mem_base != xmlMemBlocks()) {
712+ test.write(""" if (mem_base != xmlMemBlocks()) {
713 printf("Leak of %%d blocks found in %s",
714- xmlMemBlocks() - mem_base);
715- test_ret++;
716+\t xmlMemBlocks() - mem_base);
717+\t test_ret++;
718 """ % (name));
719- for arg in t_args:
720- (nam, type, rtype, crtype, info) = arg;
721- test.write(""" printf(" %%d", n_%s);\n""" % (nam))
722- test.write(""" printf("\\n");\n""")
723- test.write(" }\n")
724+ for arg in t_args:
725+ (nam, type, rtype, crtype, info) = arg;
726+ test.write(""" printf(" %%d", n_%s);\n""" % (nam))
727+ test.write(""" printf("\\n");\n""")
728+ test.write(" }\n")
729
730 for arg in t_args:
731- test.write(" }\n")
732+ test.write(" }\n")
733
734 test.write(" function_tests++;\n")
735 #
736@@ -882,7 +882,7 @@ test_%s(void) {
737 #
738 while nb_cond > 0:
739 test.write("#endif\n")
740- nb_cond = nb_cond -1
741+ nb_cond = nb_cond -1
742 if define == 1:
743 test.write("#endif\n")
744
745@@ -900,10 +900,10 @@ test_%s(void) {
746 for module in modules:
747 # gather all the functions exported by that module
748 try:
749- functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
750+ functions = ctxt.xpathEval("/api/symbols/function[@file='%s']" % (module))
751 except:
752- print "Failed to gather functions from module %s" % (module)
753- continue;
754+ print("Failed to gather functions from module %s" % (module))
755+ continue;
756
757 # iterate over all functions in the module generating the test
758 i = 0
759@@ -923,14 +923,14 @@ test_%s(void) {
760 # iterate over all functions in the module generating the call
761 for function in functions:
762 name = function.xpathEval('string(@name)')
763- if is_skipped_function(name):
764- continue
765- test.write(" test_ret += test_%s();\n" % (name))
766+ if is_skipped_function(name):
767+ continue
768+ test.write(" test_ret += test_%s();\n" % (name))
769
770 # footer
771 test.write("""
772 if (test_ret != 0)
773- printf("Module %s: %%d errors\\n", test_ret);
774+\tprintf("Module %s: %%d errors\\n", test_ret);
775 return(test_ret);
776 }
777 """ % (module))
778@@ -948,7 +948,7 @@ test.write(""" return(0);
779 }
780 """);
781
782-print "Generated test for %d modules and %d functions" %(len(modules), nb_tests)
783+print("Generated test for %d modules and %d functions" %(len(modules), nb_tests))
784
785 compare_and_save()
786
787@@ -960,11 +960,8 @@ for missing in missing_types.keys():
788 n = len(missing_types[missing])
789 missing_list.append((n, missing))
790
791-def compare_missing(a, b):
792- return b[0] - a[0]
793-
794-missing_list.sort(compare_missing)
795-print "Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list))
796+missing_list.sort(key=lambda a: a[0])
797+print("Missing support for %d functions and %d types see missing.lst" % (missing_functions_nr, len(missing_list)))
798 lst = open("missing.lst", "w")
799 lst.write("Missing support for %d types" % (len(missing_list)))
800 lst.write("\n")
801@@ -974,9 +971,9 @@ for miss in missing_list:
802 for n in missing_types[miss[1]]:
803 i = i + 1
804 if i > 5:
805- lst.write(" ...")
806- break
807- lst.write(" %s" % (n))
808+ lst.write(" ...")
809+ break
810+ lst.write(" %s" % (n))
811 lst.write("\n")
812 lst.write("\n")
813 lst.write("\n")
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch b/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch
new file mode 100644
index 0000000000..5301d05323
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2016-3709.patch
@@ -0,0 +1,89 @@
1From c1ba6f54d32b707ca6d91cb3257ce9de82876b6f Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Sat, 15 Aug 2020 18:32:29 +0200
4Subject: [PATCH] Revert "Do not URI escape in server side includes"
5
6This reverts commit 960f0e275616cadc29671a218d7fb9b69eb35588.
7
8This commit introduced
9
10- an infinite loop, found by OSS-Fuzz, which could be easily fixed.
11- an algorithm with quadratic runtime
12- a security issue, see
13 https://bugzilla.gnome.org/show_bug.cgi?id=769760
14
15A better approach is to add an option not to escape URLs at all
16which libxml2 should have possibly done in the first place.
17
18CVE: CVE-2016-3709
19Upstream-Status: Backport [https://github.com/GNOME/libxml2/commit/c1ba6f54d32b707ca6d91cb3257ce9de82876b6f]
20Signed-off-by: Pawan Badganchi <Pawan.Badganchi@kpit.com>
21---
22 HTMLtree.c | 49 +++++++++++--------------------------------------
23 1 file changed, 11 insertions(+), 38 deletions(-)
24
25diff --git a/HTMLtree.c b/HTMLtree.c
26index 8d236bb35..cdb7f86a6 100644
27--- a/HTMLtree.c
28+++ b/HTMLtree.c
29@@ -706,49 +706,22 @@ htmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
30 (!xmlStrcasecmp(cur->name, BAD_CAST "src")) ||
31 ((!xmlStrcasecmp(cur->name, BAD_CAST "name")) &&
32 (!xmlStrcasecmp(cur->parent->name, BAD_CAST "a"))))) {
33+ xmlChar *escaped;
34 xmlChar *tmp = value;
35- /* xmlURIEscapeStr() escapes '"' so it can be safely used. */
36- xmlBufCCat(buf->buffer, "\"");
37
38 while (IS_BLANK_CH(*tmp)) tmp++;
39
40- /* URI Escape everything, except server side includes. */
41- for ( ; ; ) {
42- xmlChar *escaped;
43- xmlChar endChar;
44- xmlChar *end = NULL;
45- xmlChar *start = (xmlChar *)xmlStrstr(tmp, BAD_CAST "<!--");
46- if (start != NULL) {
47- end = (xmlChar *)xmlStrstr(tmp, BAD_CAST "-->");
48- if (end != NULL) {
49- *start = '\0';
50- }
51- }
52-
53- /* Escape the whole string, or until start (set to '\0'). */
54- escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+");
55- if (escaped != NULL) {
56- xmlBufCat(buf->buffer, escaped);
57- xmlFree(escaped);
58- } else {
59- xmlBufCat(buf->buffer, tmp);
60- }
61-
62- if (end == NULL) { /* Everything has been written. */
63- break;
64- }
65-
66- /* Do not escape anything within server side includes. */
67- *start = '<'; /* Restore the first character of "<!--". */
68- end += 3; /* strlen("-->") */
69- endChar = *end;
70- *end = '\0';
71- xmlBufCat(buf->buffer, start);
72- *end = endChar;
73- tmp = end;
74+ /*
75+ * the < and > have already been escaped at the entity level
76+ * And doing so here breaks server side includes
77+ */
78+ escaped = xmlURIEscapeStr(tmp, BAD_CAST"@/:=?;#%&,+<>");
79+ if (escaped != NULL) {
80+ xmlBufWriteQuotedString(buf->buffer, escaped);
81+ xmlFree(escaped);
82+ } else {
83+ xmlBufWriteQuotedString(buf->buffer, value);
84 }
85-
86- xmlBufCCat(buf->buffer, "\"");
87 } else {
88 xmlBufWriteQuotedString(buf->buffer, value);
89 }
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch
new file mode 100644
index 0000000000..200f42091e
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3516.patch
@@ -0,0 +1,35 @@
1From 1358d157d0bd83be1dfe356a69213df9fac0b539 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 21 Apr 2021 13:23:27 +0200
4Subject: [PATCH] Fix use-after-free with `xmllint --html --push`
5
6Call htmlCtxtUseOptions to make sure that names aren't stored in
7dictionaries.
8
9Note that this issue only affects xmllint using the HTML push parser.
10
11Fixes #230.
12
13Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/1358d157d0bd83be1dfe356a69213df9fac0b539]
14CVE: CVE-2021-3516
15Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
16---
17 xmllint.c | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/xmllint.c b/xmllint.c
21index 6ca1bf54d..dbef273a8 100644
22--- a/xmllint.c
23+++ b/xmllint.c
24@@ -2213,7 +2213,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
25 if (res > 0) {
26 ctxt = htmlCreatePushParserCtxt(NULL, NULL,
27 chars, res, filename, XML_CHAR_ENCODING_NONE);
28- xmlCtxtUseOptions(ctxt, options);
29+ htmlCtxtUseOptions(ctxt, options);
30 while ((res = fread(chars, 1, pushsize, f)) > 0) {
31 htmlParseChunk(ctxt, chars, res, 0);
32 }
33--
34GitLab
35
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3517.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3517.patch
new file mode 100644
index 0000000000..e88a8ae7c6
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3517.patch
@@ -0,0 +1,53 @@
1From bf22713507fe1fc3a2c4b525cf0a88c2dc87a3a2 Mon Sep 17 00:00:00 2001
2From: Joel Hockey <joel.hockey@gmail.com>
3Date: Sun, 16 Aug 2020 17:19:35 -0700
4Subject: [PATCH] Validate UTF8 in xmlEncodeEntities
5
6Code is currently assuming UTF-8 without validating. Truncated UTF-8
7input can cause out-of-bounds array access.
8
9Adds further checks to partial fix in 50f06b3e.
10
11Fixes #178
12Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/bf22713507fe1fc3a2c4b525cf0a88c2dc87a3a2]
13CVE: CVE-2021-3517
14Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
15
16---
17 entities.c | 16 +++++++++++++++-
18 1 file changed, 15 insertions(+), 1 deletion(-)
19
20diff --git a/entities.c b/entities.c
21index 37b99a56..1a8f86f0 100644
22--- a/entities.c
23+++ b/entities.c
24@@ -704,11 +704,25 @@ xmlEncodeEntitiesInternal(xmlDocPtr doc, const xmlChar *input, int attr) {
25 } else {
26 /*
27 * We assume we have UTF-8 input.
28+ * It must match either:
29+ * 110xxxxx 10xxxxxx
30+ * 1110xxxx 10xxxxxx 10xxxxxx
31+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
32+ * That is:
33+ * cur[0] is 11xxxxxx
34+ * cur[1] is 10xxxxxx
35+ * cur[2] is 10xxxxxx if cur[0] is 111xxxxx
36+ * cur[3] is 10xxxxxx if cur[0] is 1111xxxx
37+ * cur[0] is not 11111xxx
38 */
39 char buf[11], *ptr;
40 int val = 0, l = 1;
41
42- if (*cur < 0xC0) {
43+ if (((cur[0] & 0xC0) != 0xC0) ||
44+ ((cur[1] & 0xC0) != 0x80) ||
45+ (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
46+ (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
47+ (((cur[0] & 0xF8) == 0xF8))) {
48 xmlEntitiesErr(XML_CHECK_NOT_UTF8,
49 "xmlEncodeEntities: input not UTF-8");
50 if (doc != NULL)
51--
52GitLab
53
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch
new file mode 100644
index 0000000000..40d3debea1
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3518.patch
@@ -0,0 +1,112 @@
1From ac82a514e16eb81b4506e2cba1a1ee45b9f025b5 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 10 Jun 2020 16:34:52 +0200
4Subject: [PATCH 1/2] Don't recurse into xi:include children in
5 xmlXIncludeDoProcess
6
7Otherwise, nested xi:include nodes might result in a use-after-free
8if XML_PARSE_NOXINCNODE is specified.
9
10Found with libFuzzer and ASan.
11
12Upstream-Status: Backport [from fedora: https://bugzilla.redhat.com/show_bug.cgi?id=1954243]
13
14The upstream patch 752e5f71d7cea2ca5a7e7c0b8f72ed04ce654be4 has been modified,
15as to avoid unnecessary modifications to fallback files.
16
17CVE: CVE-2021-3518
18Signed-off-by: Jasper Orschulko <Jasper.Orschulko@iris-sensing.com>
19---
20 xinclude.c | 24 ++++++++++--------------
21 1 file changed, 10 insertions(+), 14 deletions(-)
22
23diff --git a/xinclude.c b/xinclude.c
24index ba850fa5..f260c1a7 100644
25--- a/xinclude.c
26+++ b/xinclude.c
27@@ -2392,21 +2392,19 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
28 * First phase: lookup the elements in the document
29 */
30 cur = tree;
31- if (xmlXIncludeTestNode(ctxt, cur) == 1)
32- xmlXIncludePreProcessNode(ctxt, cur);
33 while ((cur != NULL) && (cur != tree->parent)) {
34 /* TODO: need to work on entities -> stack */
35- if ((cur->children != NULL) &&
36- (cur->children->type != XML_ENTITY_DECL) &&
37- (cur->children->type != XML_XINCLUDE_START) &&
38- (cur->children->type != XML_XINCLUDE_END)) {
39- cur = cur->children;
40- if (xmlXIncludeTestNode(ctxt, cur))
41- xmlXIncludePreProcessNode(ctxt, cur);
42- } else if (cur->next != NULL) {
43+ if (xmlXIncludeTestNode(ctxt, cur) == 1) {
44+ xmlXIncludePreProcessNode(ctxt, cur);
45+ } else if ((cur->children != NULL) &&
46+ (cur->children->type != XML_ENTITY_DECL) &&
47+ (cur->children->type != XML_XINCLUDE_START) &&
48+ (cur->children->type != XML_XINCLUDE_END)) {
49+ cur = cur->children;
50+ continue;
51+ }
52+ if (cur->next != NULL) {
53 cur = cur->next;
54- if (xmlXIncludeTestNode(ctxt, cur))
55- xmlXIncludePreProcessNode(ctxt, cur);
56 } else {
57 if (cur == tree)
58 break;
59@@ -2416,8 +2414,6 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
60 break; /* do */
61 if (cur->next != NULL) {
62 cur = cur->next;
63- if (xmlXIncludeTestNode(ctxt, cur))
64- xmlXIncludePreProcessNode(ctxt, cur);
65 break; /* do */
66 }
67 } while (cur != NULL);
68--
692.32.0
70
71
72From 3ad5ac1e39e3cd42f838c1cd27ffd4e9b79e6121 Mon Sep 17 00:00:00 2001
73From: Nick Wellnhofer <wellnhofer@aevum.de>
74Date: Thu, 22 Apr 2021 19:26:28 +0200
75Subject: [PATCH 2/2] Fix user-after-free with `xmllint --xinclude --dropdtd`
76
77The --dropdtd option can leave dangling pointers in entity reference
78nodes. Make sure to skip these nodes when processing XIncludes.
79
80This also avoids scanning entity declarations and even modifying
81them inadvertently during XInclude processing.
82
83Move from a block list to an allow list approach to avoid descending
84into other node types that can't contain elements.
85
86Fixes #237.
87Upstream-Status: Backport
88CVE: CVE-2021-3518
89Signed-off-by: Jasper Orschulko <Jasper.Orschulko@iris-sensing.com>
90---
91 xinclude.c | 5 ++---
92 1 file changed, 2 insertions(+), 3 deletions(-)
93
94diff --git a/xinclude.c b/xinclude.c
95index f260c1a7..d7648529 100644
96--- a/xinclude.c
97+++ b/xinclude.c
98@@ -2397,9 +2397,8 @@ xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) {
99 if (xmlXIncludeTestNode(ctxt, cur) == 1) {
100 xmlXIncludePreProcessNode(ctxt, cur);
101 } else if ((cur->children != NULL) &&
102- (cur->children->type != XML_ENTITY_DECL) &&
103- (cur->children->type != XML_XINCLUDE_START) &&
104- (cur->children->type != XML_XINCLUDE_END)) {
105+ ((cur->type == XML_DOCUMENT_NODE) ||
106+ (cur->type == XML_ELEMENT_NODE))) {
107 cur = cur->children;
108 continue;
109 }
110--
1112.32.0
112
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3537.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3537.patch
new file mode 100644
index 0000000000..9e64c2a36d
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3537.patch
@@ -0,0 +1,50 @@
1From babe75030c7f64a37826bb3342317134568bef61 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Sat, 1 May 2021 16:53:33 +0200
4Subject: [PATCH] Propagate error in xmlParseElementChildrenContentDeclPriv
5
6Check return value of recursive calls to
7xmlParseElementChildrenContentDeclPriv and return immediately in case
8of errors. Otherwise, struct xmlElementContent could contain unexpected
9null pointers, leading to a null deref when post-validating documents
10which aren't well-formed and parsed in recovery mode.
11
12Fixes #243.
13
14Upstream-Status: Backport
15[https://gitlab.gnome.org/GNOME/libxml2/-/commit/babe75030c7f64a37826bb3342317134568bef61]
16CVE: CVE-2021-3537
17Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
18
19---
20 parser.c | 7 +++++++
21 1 file changed, 7 insertions(+)
22
23diff --git a/parser.c b/parser.c
24index b42e6043..73c27edd 100644
25--- a/parser.c
26+++ b/parser.c
27@@ -6208,6 +6208,8 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
28 SKIP_BLANKS;
29 cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
30 depth + 1);
31+ if (cur == NULL)
32+ return(NULL);
33 SKIP_BLANKS;
34 GROW;
35 } else {
36@@ -6341,6 +6343,11 @@ xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
37 SKIP_BLANKS;
38 last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
39 depth + 1);
40+ if (last == NULL) {
41+ if (ret != NULL)
42+ xmlFreeDocElementContent(ctxt->myDoc, ret);
43+ return(NULL);
44+ }
45 SKIP_BLANKS;
46 } else {
47 elem = xmlParseName(ctxt);
48--
49GitLab
50
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch b/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch
new file mode 100644
index 0000000000..1f392b4cd7
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2021-3541.patch
@@ -0,0 +1,73 @@
1From 8598060bacada41a0eb09d95c97744ff4e428f8e Mon Sep 17 00:00:00 2001
2From: Daniel Veillard <veillard@redhat.com>
3Date: Thu, 13 May 2021 14:55:12 +0200
4Subject: [PATCH] Patch for security issue CVE-2021-3541
5
6This is relapted to parameter entities expansion and following
7the line of the billion laugh attack. Somehow in that path the
8counting of parameters was missed and the normal algorithm based
9on entities "density" was useless.
10
11Upstream-Status: Backport
12[https://gitlab.gnome.org/GNOME/libxml2/-/commit/8598060bacada41a0eb09d95c97744ff4e428f8e]
13CVE: CVE-2021-3541
14Signed-off-by: Steve Sakoman <steve@sakoman.com>
15
16---
17 parser.c | 26 ++++++++++++++++++++++++++
18 1 file changed, 26 insertions(+)
19
20diff --git a/parser.c b/parser.c
21index f5e5e169..c9312fa4 100644
22--- a/parser.c
23+++ b/parser.c
24@@ -140,6 +140,7 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
25 xmlEntityPtr ent, size_t replacement)
26 {
27 size_t consumed = 0;
28+ int i;
29
30 if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
31 return (0);
32@@ -177,6 +178,28 @@ xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
33 rep = NULL;
34 }
35 }
36+
37+ /*
38+ * Prevent entity exponential check, not just replacement while
39+ * parsing the DTD
40+ * The check is potentially costly so do that only once in a thousand
41+ */
42+ if ((ctxt->instate == XML_PARSER_DTD) && (ctxt->nbentities > 10000) &&
43+ (ctxt->nbentities % 1024 == 0)) {
44+ for (i = 0;i < ctxt->inputNr;i++) {
45+ consumed += ctxt->inputTab[i]->consumed +
46+ (ctxt->inputTab[i]->cur - ctxt->inputTab[i]->base);
47+ }
48+ if (ctxt->nbentities > consumed * XML_PARSER_NON_LINEAR) {
49+ xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
50+ ctxt->instate = XML_PARSER_EOF;
51+ return (1);
52+ }
53+ consumed = 0;
54+ }
55+
56+
57+
58 if (replacement != 0) {
59 if (replacement < XML_MAX_TEXT_LENGTH)
60 return(0);
61@@ -7963,6 +7986,9 @@ xmlParsePEReference(xmlParserCtxtPtr ctxt)
62 xmlChar start[4];
63 xmlCharEncoding enc;
64
65+ if (xmlParserEntityCheck(ctxt, 0, entity, 0))
66+ return;
67+
68 if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
69 ((ctxt->options & XML_PARSE_NOENT) == 0) &&
70 ((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
71--
72GitLab
73
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch
new file mode 100644
index 0000000000..7fc243eec1
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch
@@ -0,0 +1,98 @@
1From 646fe48d1c8a74310c409ddf81fe7df6700052af Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Tue, 22 Feb 2022 11:51:08 +0100
4Subject: [PATCH] Fix --without-valid build
5
6Regressed in commit 652dd12a.
7---
8 valid.c | 58 ++++++++++++++++++++++++++++-----------------------------
9 1 file changed, 29 insertions(+), 29 deletions(-)
10---
11
12From https://github.com/GNOME/libxml2.git
13 commit 646fe48d1c8a74310c409ddf81fe7df6700052af
14
15CVE: CVE-2022-23308
16Upstream-Status: Backport
17
18Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
19
20diff --git a/valid.c b/valid.c
21index 8e596f1d..9684683a 100644
22--- a/valid.c
23+++ b/valid.c
24@@ -479,35 +479,6 @@ nodeVPop(xmlValidCtxtPtr ctxt)
25 return (ret);
26 }
27
28-/**
29- * xmlValidNormalizeString:
30- * @str: a string
31- *
32- * Normalize a string in-place.
33- */
34-static void
35-xmlValidNormalizeString(xmlChar *str) {
36- xmlChar *dst;
37- const xmlChar *src;
38-
39- if (str == NULL)
40- return;
41- src = str;
42- dst = str;
43-
44- while (*src == 0x20) src++;
45- while (*src != 0) {
46- if (*src == 0x20) {
47- while (*src == 0x20) src++;
48- if (*src != 0)
49- *dst++ = 0x20;
50- } else {
51- *dst++ = *src++;
52- }
53- }
54- *dst = 0;
55-}
56-
57 #ifdef DEBUG_VALID_ALGO
58 static void
59 xmlValidPrintNode(xmlNodePtr cur) {
60@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
61 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
62 xmlFree((char *)(str));
63
64+/**
65+ * xmlValidNormalizeString:
66+ * @str: a string
67+ *
68+ * Normalize a string in-place.
69+ */
70+static void
71+xmlValidNormalizeString(xmlChar *str) {
72+ xmlChar *dst;
73+ const xmlChar *src;
74+
75+ if (str == NULL)
76+ return;
77+ src = str;
78+ dst = str;
79+
80+ while (*src == 0x20) src++;
81+ while (*src != 0) {
82+ if (*src == 0x20) {
83+ while (*src == 0x20) src++;
84+ if (*src != 0)
85+ *dst++ = 0x20;
86+ } else {
87+ *dst++ = *src++;
88+ }
89+ }
90+ *dst = 0;
91+}
92+
93 static int
94 xmlIsStreaming(xmlValidCtxtPtr ctxt) {
95 xmlParserCtxtPtr pctxt;
96--
972.35.1
98
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch
new file mode 100644
index 0000000000..bf5604e81a
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch
@@ -0,0 +1,204 @@
1From 8b66850de350f0fcd786ae776a65ba15a5999e50 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Tue, 8 Feb 2022 03:29:24 +0100
4Subject: [PATCH] Use-after-free of ID and IDREF attributes
5
6If a document is parsed with XML_PARSE_DTDVALID and without
7XML_PARSE_NOENT, the value of ID attributes has to be normalized after
8potentially expanding entities in xmlRemoveID. Otherwise, later calls
9to xmlGetID can return a pointer to previously freed memory.
10
11ID attributes which are empty or contain only whitespace after
12entity expansion are affected in a similar way. This is fixed by
13not storing such attributes in the ID table.
14
15The test to detect streaming mode when validating against a DTD was
16broken. In connection with the defects above, this could result in a
17use-after-free when using the xmlReader interface with validation.
18Fix detection of streaming mode to avoid similar issues. (This changes
19the expected result of a test case. But as far as I can tell, using the
20XML reader with XIncludes referencing the root document never worked
21properly, anyway.)
22
23All of these issues can result in denial of service. Using xmlReader
24with validation could result in disclosure of memory via the error
25channel, typically stderr. The security impact of xmlGetID returning
26a pointer to freed memory depends on the application. The typical use
27case of calling xmlGetID on an unmodified document is not affected.
28
29Upstream-Status: Backport
30[https://gitlab.gnome.org/GNOME/libxml2/-/commit/652dd12a858989b14eed4e84e453059cd3ba340e]
31
32The upstream patch 652dd12a858989b14eed4e84e453059cd3ba340e has been modified
33to skip the patch to the testsuite result (result/XInclude/ns1.xml.rdr), as
34this particular test does not exist in v2.9.10 (it was added later).
35
36CVE: CVE-2022-23308
37Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
38
39---
40 valid.c | 88 +++++++++++++++++++++++++++++++++++----------------------
41 1 file changed, 55 insertions(+), 33 deletions(-)
42
43diff --git a/valid.c b/valid.c
44index 07963e7..ee75311 100644
45--- a/valid.c
46+++ b/valid.c
47@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt)
48 return (ret);
49 }
50
51+/**
52+ * xmlValidNormalizeString:
53+ * @str: a string
54+ *
55+ * Normalize a string in-place.
56+ */
57+static void
58+xmlValidNormalizeString(xmlChar *str) {
59+ xmlChar *dst;
60+ const xmlChar *src;
61+
62+ if (str == NULL)
63+ return;
64+ src = str;
65+ dst = str;
66+
67+ while (*src == 0x20) src++;
68+ while (*src != 0) {
69+ if (*src == 0x20) {
70+ while (*src == 0x20) src++;
71+ if (*src != 0)
72+ *dst++ = 0x20;
73+ } else {
74+ *dst++ = *src++;
75+ }
76+ }
77+ *dst = 0;
78+}
79+
80 #ifdef DEBUG_VALID_ALGO
81 static void
82 xmlValidPrintNode(xmlNodePtr cur) {
83@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
84 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
85 xmlFree((char *)(str));
86
87+static int
88+xmlIsStreaming(xmlValidCtxtPtr ctxt) {
89+ xmlParserCtxtPtr pctxt;
90+
91+ if (ctxt == NULL)
92+ return(0);
93+ /*
94+ * These magic values are also abused to detect whether we're validating
95+ * while parsing a document. In this case, userData points to the parser
96+ * context.
97+ */
98+ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) &&
99+ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1))
100+ return(0);
101+ pctxt = ctxt->userData;
102+ return(pctxt->parseMode == XML_PARSE_READER);
103+}
104+
105 /**
106 * xmlFreeID:
107 * @not: A id
108@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
109 if (doc == NULL) {
110 return(NULL);
111 }
112- if (value == NULL) {
113+ if ((value == NULL) || (value[0] == 0)) {
114 return(NULL);
115 }
116 if (attr == NULL) {
117@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
118 */
119 ret->value = xmlStrdup(value);
120 ret->doc = doc;
121- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
122+ if (xmlIsStreaming(ctxt)) {
123 /*
124 * Operating in streaming mode, attr is gonna disappear
125 */
126@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
127 ID = xmlNodeListGetString(doc, attr->children, 1);
128 if (ID == NULL)
129 return(-1);
130+ xmlValidNormalizeString(ID);
131
132 id = xmlHashLookup(table, ID);
133 if (id == NULL || id->attr != attr) {
134@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
135 * fill the structure.
136 */
137 ret->value = xmlStrdup(value);
138- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
139+ if (xmlIsStreaming(ctxt)) {
140 /*
141 * Operating in streaming mode, attr is gonna disappear
142 */
143@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
144 xmlChar *
145 xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
146 xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
147- xmlChar *ret, *dst;
148- const xmlChar *src;
149+ xmlChar *ret;
150 xmlAttributePtr attrDecl = NULL;
151 int extsubset = 0;
152
153@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
154 ret = xmlStrdup(value);
155 if (ret == NULL)
156 return(NULL);
157- src = value;
158- dst = ret;
159- while (*src == 0x20) src++;
160- while (*src != 0) {
161- if (*src == 0x20) {
162- while (*src == 0x20) src++;
163- if (*src != 0)
164- *dst++ = 0x20;
165- } else {
166- *dst++ = *src++;
167- }
168- }
169- *dst = 0;
170+ xmlValidNormalizeString(ret);
171 if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
172 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
173 "standalone: %s on %s value had to be normalized based on external subset declaration\n",
174@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
175 xmlChar *
176 xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
177 const xmlChar *name, const xmlChar *value) {
178- xmlChar *ret, *dst;
179- const xmlChar *src;
180+ xmlChar *ret;
181 xmlAttributePtr attrDecl = NULL;
182
183 if (doc == NULL) return(NULL);
184@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
185 ret = xmlStrdup(value);
186 if (ret == NULL)
187 return(NULL);
188- src = value;
189- dst = ret;
190- while (*src == 0x20) src++;
191- while (*src != 0) {
192- if (*src == 0x20) {
193- while (*src == 0x20) src++;
194- if (*src != 0)
195- *dst++ = 0x20;
196- } else {
197- *dst++ = *src++;
198- }
199- }
200- *dst = 0;
201+ xmlValidNormalizeString(ret);
202 return(ret);
203 }
204
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch
new file mode 100644
index 0000000000..63d613cc21
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-29824-dependent.patch
@@ -0,0 +1,53 @@
1From b07251215ef48c70c6e56f7351406c47cfca4d5b Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Fri, 10 Jan 2020 15:55:07 +0100
4Subject: [PATCH] Fix integer overflow in xmlBufferResize
5
6Found by OSS-Fuzz.
7
8CVE: CVE-2022-29824
9
10Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/b07251215ef48c70c6e56f7351406c47cfca4d5b]
11
12Signed-off-by: Riyaz Ahmed Khan <Riyaz.Khan@kpit.com>
13
14---
15 tree.c | 9 +++++++--
16 1 file changed, 7 insertions(+), 2 deletions(-)
17
18diff --git a/tree.c b/tree.c
19index 0d7fc98c..f43f6de1 100644
20--- a/tree.c
21+++ b/tree.c
22@@ -7424,12 +7424,17 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
23 if (size < buf->size)
24 return 1;
25
26+ if (size > UINT_MAX - 10) {
27+ xmlTreeErrMemory("growing buffer");
28+ return 0;
29+ }
30+
31 /* figure out new size */
32 switch (buf->alloc){
33 case XML_BUFFER_ALLOC_IO:
34 case XML_BUFFER_ALLOC_DOUBLEIT:
35 /*take care of empty case*/
36- newSize = (buf->size ? buf->size*2 : size + 10);
37+ newSize = (buf->size ? buf->size : size + 10);
38 while (size > newSize) {
39 if (newSize > UINT_MAX / 2) {
40 xmlTreeErrMemory("growing buffer");
41@@ -7445,7 +7450,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
42 if (buf->use < BASE_BUFFER_SIZE)
43 newSize = size;
44 else {
45- newSize = buf->size * 2;
46+ newSize = buf->size;
47 while (size > newSize) {
48 if (newSize > UINT_MAX / 2) {
49 xmlTreeErrMemory("growing buffer");
50--
51GitLab
52
53
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch
new file mode 100644
index 0000000000..ad7b87dbc6
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-29824.patch
@@ -0,0 +1,348 @@
1From 2554a2408e09f13652049e5ffb0d26196b02ebab Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Tue, 8 Mar 2022 20:10:02 +0100
4Subject: [PATCH] [CVE-2022-29824] Fix integer overflows in xmlBuf and
5 xmlBuffer
6
7In several places, the code handling string buffers didn't check for
8integer overflow or used wrong types for buffer sizes. This could
9result in out-of-bounds writes or other memory errors when working on
10large, multi-gigabyte buffers.
11
12Thanks to Felix Wilhelm for the report.
13
14CVE: CVE-2022-29824
15
16Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/2554a2408e09f13652049e5ffb0d26196b02ebab]
17
18Signed-off-by: Riyaz Ahmed Khan <Riyaz.Khan@kpit.com>
19
20---
21 buf.c | 86 +++++++++++++++++++++++-----------------------------------
22 tree.c | 72 ++++++++++++++++++------------------------------
23 2 files changed, 61 insertions(+), 97 deletions(-)
24
25diff --git a/buf.c b/buf.c
26index 24368d37..40a5ee06 100644
27--- a/buf.c
28+++ b/buf.c
29@@ -30,6 +30,10 @@
30 #include <libxml/parserInternals.h> /* for XML_MAX_TEXT_LENGTH */
31 #include "buf.h"
32
33+#ifndef SIZE_MAX
34+#define SIZE_MAX ((size_t) -1)
35+#endif
36+
37 #define WITH_BUFFER_COMPAT
38
39 /**
40@@ -156,6 +160,8 @@ xmlBufPtr
41 xmlBufCreateSize(size_t size) {
42 xmlBufPtr ret;
43
44+ if (size == SIZE_MAX)
45+ return(NULL);
46 ret = (xmlBufPtr) xmlMalloc(sizeof(xmlBuf));
47 if (ret == NULL) {
48 xmlBufMemoryError(NULL, "creating buffer");
49@@ -166,8 +172,8 @@ xmlBufCreateSize(size_t size) {
50 ret->error = 0;
51 ret->buffer = NULL;
52 ret->alloc = xmlBufferAllocScheme;
53- ret->size = (size ? size+2 : 0); /* +1 for ending null */
54- ret->compat_size = (int) ret->size;
55+ ret->size = (size ? size + 1 : 0); /* +1 for ending null */
56+ ret->compat_size = (ret->size > INT_MAX ? INT_MAX : ret->size);
57 if (ret->size){
58 ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
59 if (ret->content == NULL) {
60@@ -442,23 +448,17 @@ xmlBufGrowInternal(xmlBufPtr buf, size_t len) {
61 CHECK_COMPAT(buf)
62
63 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
64- if (buf->use + len < buf->size)
65+ if (len < buf->size - buf->use)
66 return(buf->size - buf->use);
67+ if (len > SIZE_MAX - buf->use)
68+ return(0);
69
70- /*
71- * Windows has a BIG problem on realloc timing, so we try to double
72- * the buffer size (if that's enough) (bug 146697)
73- * Apparently BSD too, and it's probably best for linux too
74- * On an embedded system this may be something to change
75- */
76-#if 1
77- if (buf->size > (size_t) len)
78- size = buf->size * 2;
79- else
80- size = buf->use + len + 100;
81-#else
82- size = buf->use + len + 100;
83-#endif
84+ if (buf->size > (size_t) len) {
85+ size = buf->size > SIZE_MAX / 2 ? SIZE_MAX : buf->size * 2;
86+ } else {
87+ size = buf->use + len;
88+ size = size > SIZE_MAX - 100 ? SIZE_MAX : size + 100;
89+ }
90
91 if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
92 /*
93@@ -744,7 +744,7 @@ xmlBufIsEmpty(const xmlBufPtr buf)
94 int
95 xmlBufResize(xmlBufPtr buf, size_t size)
96 {
97- unsigned int newSize;
98+ size_t newSize;
99 xmlChar* rebuf = NULL;
100 size_t start_buf;
101
102@@ -772,9 +772,13 @@ xmlBufResize(xmlBufPtr buf, size_t size)
103 case XML_BUFFER_ALLOC_IO:
104 case XML_BUFFER_ALLOC_DOUBLEIT:
105 /*take care of empty case*/
106- newSize = (buf->size ? buf->size*2 : size + 10);
107+ if (buf->size == 0) {
108+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
109+ } else {
110+ newSize = buf->size;
111+ }
112 while (size > newSize) {
113- if (newSize > UINT_MAX / 2) {
114+ if (newSize > SIZE_MAX / 2) {
115 xmlBufMemoryError(buf, "growing buffer");
116 return 0;
117 }
118@@ -782,15 +786,15 @@ xmlBufResize(xmlBufPtr buf, size_t size)
119 }
120 break;
121 case XML_BUFFER_ALLOC_EXACT:
122- newSize = size+10;
123+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
124 break;
125 case XML_BUFFER_ALLOC_HYBRID:
126 if (buf->use < BASE_BUFFER_SIZE)
127 newSize = size;
128 else {
129- newSize = buf->size * 2;
130+ newSize = buf->size;
131 while (size > newSize) {
132- if (newSize > UINT_MAX / 2) {
133+ if (newSize > SIZE_MAX / 2) {
134 xmlBufMemoryError(buf, "growing buffer");
135 return 0;
136 }
137@@ -800,7 +804,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
138 break;
139
140 default:
141- newSize = size+10;
142+ newSize = (size > SIZE_MAX - 10 ? SIZE_MAX : size + 10);
143 break;
144 }
145
146@@ -866,7 +870,7 @@ xmlBufResize(xmlBufPtr buf, size_t size)
147 */
148 int
149 xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
150- unsigned int needSize;
151+ size_t needSize;
152
153 if ((str == NULL) || (buf == NULL) || (buf->error))
154 return -1;
155@@ -888,8 +892,10 @@ xmlBufAdd(xmlBufPtr buf, const xmlChar *str, int len) {
156 if (len < 0) return -1;
157 if (len == 0) return 0;
158
159- needSize = buf->use + len + 2;
160- if (needSize > buf->size){
161+ if ((size_t) len >= buf->size - buf->use) {
162+ if ((size_t) len >= SIZE_MAX - buf->use)
163+ return(-1);
164+ needSize = buf->use + len + 1;
165 if (buf->alloc == XML_BUFFER_ALLOC_BOUNDED) {
166 /*
167 * Used to provide parsing limits
168@@ -1025,31 +1031,7 @@ xmlBufCat(xmlBufPtr buf, const xmlChar *str) {
169 */
170 int
171 xmlBufCCat(xmlBufPtr buf, const char *str) {
172- const char *cur;
173-
174- if ((buf == NULL) || (buf->error))
175- return(-1);
176- CHECK_COMPAT(buf)
177- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
178- if (str == NULL) {
179-#ifdef DEBUG_BUFFER
180- xmlGenericError(xmlGenericErrorContext,
181- "xmlBufCCat: str == NULL\n");
182-#endif
183- return -1;
184- }
185- for (cur = str;*cur != 0;cur++) {
186- if (buf->use + 10 >= buf->size) {
187- if (!xmlBufResize(buf, buf->use+10)){
188- xmlBufMemoryError(buf, "growing buffer");
189- return XML_ERR_NO_MEMORY;
190- }
191- }
192- buf->content[buf->use++] = *cur;
193- }
194- buf->content[buf->use] = 0;
195- UPDATE_COMPAT(buf)
196- return 0;
197+ return xmlBufCat(buf, (const xmlChar *) str);
198 }
199
200 /**
201diff --git a/tree.c b/tree.c
202index 9d94aa42..86afb7d6 100644
203--- a/tree.c
204+++ b/tree.c
205@@ -7104,6 +7104,8 @@ xmlBufferPtr
206 xmlBufferCreateSize(size_t size) {
207 xmlBufferPtr ret;
208
209+ if (size >= UINT_MAX)
210+ return(NULL);
211 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
212 if (ret == NULL) {
213 xmlTreeErrMemory("creating buffer");
214@@ -7111,7 +7113,7 @@ xmlBufferCreateSize(size_t size) {
215 }
216 ret->use = 0;
217 ret->alloc = xmlBufferAllocScheme;
218- ret->size = (size ? size+2 : 0); /* +1 for ending null */
219+ ret->size = (size ? size + 1 : 0); /* +1 for ending null */
220 if (ret->size){
221 ret->content = (xmlChar *) xmlMallocAtomic(ret->size * sizeof(xmlChar));
222 if (ret->content == NULL) {
223@@ -7171,6 +7173,8 @@ xmlBufferCreateStatic(void *mem, size_t size) {
224
225 if ((mem == NULL) || (size == 0))
226 return(NULL);
227+ if (size > UINT_MAX)
228+ return(NULL);
229
230 ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer));
231 if (ret == NULL) {
232@@ -7318,28 +7322,23 @@ xmlBufferShrink(xmlBufferPtr buf, unsigned int len) {
233 */
234 int
235 xmlBufferGrow(xmlBufferPtr buf, unsigned int len) {
236- int size;
237+ unsigned int size;
238 xmlChar *newbuf;
239
240 if (buf == NULL) return(-1);
241
242 if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return(0);
243- if (len + buf->use < buf->size) return(0);
244+ if (len < buf->size - buf->use)
245+ return(0);
246+ if (len > UINT_MAX - buf->use)
247+ return(-1);
248
249- /*
250- * Windows has a BIG problem on realloc timing, so we try to double
251- * the buffer size (if that's enough) (bug 146697)
252- * Apparently BSD too, and it's probably best for linux too
253- * On an embedded system this may be something to change
254- */
255-#if 1
256- if (buf->size > len)
257- size = buf->size * 2;
258- else
259- size = buf->use + len + 100;
260-#else
261- size = buf->use + len + 100;
262-#endif
263+ if (buf->size > (size_t) len) {
264+ size = buf->size > UINT_MAX / 2 ? UINT_MAX : buf->size * 2;
265+ } else {
266+ size = buf->use + len;
267+ size = size > UINT_MAX - 100 ? UINT_MAX : size + 100;
268+ }
269
270 if ((buf->alloc == XML_BUFFER_ALLOC_IO) && (buf->contentIO != NULL)) {
271 size_t start_buf = buf->content - buf->contentIO;
272@@ -7466,7 +7465,10 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
273 case XML_BUFFER_ALLOC_IO:
274 case XML_BUFFER_ALLOC_DOUBLEIT:
275 /*take care of empty case*/
276- newSize = (buf->size ? buf->size : size + 10);
277+ if (buf->size == 0)
278+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);
279+ else
280+ newSize = buf->size;
281 while (size > newSize) {
282 if (newSize > UINT_MAX / 2) {
283 xmlTreeErrMemory("growing buffer");
284@@ -7476,7 +7478,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
285 }
286 break;
287 case XML_BUFFER_ALLOC_EXACT:
288- newSize = size+10;
289+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
290 break;
291 case XML_BUFFER_ALLOC_HYBRID:
292 if (buf->use < BASE_BUFFER_SIZE)
293@@ -7494,7 +7496,7 @@ xmlBufferResize(xmlBufferPtr buf, unsigned int size)
294 break;
295
296 default:
297- newSize = size+10;
298+ newSize = (size > UINT_MAX - 10 ? UINT_MAX : size + 10);;
299 break;
300 }
301
302@@ -7580,8 +7582,10 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
303 if (len < 0) return -1;
304 if (len == 0) return 0;
305
306- needSize = buf->use + len + 2;
307- if (needSize > buf->size){
308+ if ((unsigned) len >= buf->size - buf->use) {
309+ if ((unsigned) len >= UINT_MAX - buf->use)
310+ return XML_ERR_NO_MEMORY;
311+ needSize = buf->use + len + 1;
312 if (!xmlBufferResize(buf, needSize)){
313 xmlTreeErrMemory("growing buffer");
314 return XML_ERR_NO_MEMORY;
315@@ -7694,29 +7698,7 @@ xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) {
316 */
317 int
318 xmlBufferCCat(xmlBufferPtr buf, const char *str) {
319- const char *cur;
320-
321- if (buf == NULL)
322- return(-1);
323- if (buf->alloc == XML_BUFFER_ALLOC_IMMUTABLE) return -1;
324- if (str == NULL) {
325-#ifdef DEBUG_BUFFER
326- xmlGenericError(xmlGenericErrorContext,
327- "xmlBufferCCat: str == NULL\n");
328-#endif
329- return -1;
330- }
331- for (cur = str;*cur != 0;cur++) {
332- if (buf->use + 10 >= buf->size) {
333- if (!xmlBufferResize(buf, buf->use+10)){
334- xmlTreeErrMemory("growing buffer");
335- return XML_ERR_NO_MEMORY;
336- }
337- }
338- buf->content[buf->use++] = *cur;
339- }
340- buf->content[buf->use] = 0;
341- return 0;
342+ return xmlBufferCat(buf, (const xmlChar *) str);
343 }
344
345 /**
346--
347GitLab
348
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch
new file mode 100644
index 0000000000..bdb9e9eb7a
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-40303.patch
@@ -0,0 +1,623 @@
1From c846986356fc149915a74972bf198abc266bc2c0 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Thu, 25 Aug 2022 17:43:08 +0200
4Subject: [PATCH] [CVE-2022-40303] Fix integer overflows with XML_PARSE_HUGE
5
6Also impose size limits when XML_PARSE_HUGE is set. Limit size of names
7to XML_MAX_TEXT_LENGTH (10 million bytes) and other content to
8XML_MAX_HUGE_LENGTH (1 billion bytes).
9
10Move some the length checks to the end of the respective loop to make
11them strict.
12
13xmlParseEntityValue didn't have a length limitation at all. But without
14XML_PARSE_HUGE, this should eventually trigger an error in xmlGROW.
15
16Thanks to Maddie Stone working with Google Project Zero for the report!
17
18CVE: CVE-2022-40303
19Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/c846986356fc149915a74972bf198abc266bc2c0]
20Comments: Refreshed hunk
21
22Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com>
23---
24 parser.c | 233 +++++++++++++++++++++++++++++--------------------------
25 1 file changed, 121 insertions(+), 112 deletions(-)
26
27diff --git a/parser.c b/parser.c
28index 93f031be..79479979 100644
29--- a/parser.c
30+++ b/parser.c
31@@ -102,6 +102,8 @@ xmlParseElementEnd(xmlParserCtxtPtr ctxt);
32 * *
33 ************************************************************************/
34
35+#define XML_MAX_HUGE_LENGTH 1000000000
36+
37 #define XML_PARSER_BIG_ENTITY 1000
38 #define XML_PARSER_LOT_ENTITY 5000
39
40@@ -552,7 +554,7 @@ xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
41 errmsg = "Malformed declaration expecting version";
42 break;
43 case XML_ERR_NAME_TOO_LONG:
44- errmsg = "Name too long use XML_PARSE_HUGE option";
45+ errmsg = "Name too long";
46 break;
47 #if 0
48 case:
49@@ -3202,6 +3204,9 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
50 int len = 0, l;
51 int c;
52 int count = 0;
53+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
54+ XML_MAX_TEXT_LENGTH :
55+ XML_MAX_NAME_LENGTH;
56
57 #ifdef DEBUG
58 nbParseNameComplex++;
59@@ -3267,7 +3272,8 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
60 if (ctxt->instate == XML_PARSER_EOF)
61 return(NULL);
62 }
63- len += l;
64+ if (len <= INT_MAX - l)
65+ len += l;
66 NEXTL(l);
67 c = CUR_CHAR(l);
68 }
69@@ -3293,13 +3299,13 @@ xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
70 if (ctxt->instate == XML_PARSER_EOF)
71 return(NULL);
72 }
73- len += l;
74+ if (len <= INT_MAX - l)
75+ len += l;
76 NEXTL(l);
77 c = CUR_CHAR(l);
78 }
79 }
80- if ((len > XML_MAX_NAME_LENGTH) &&
81- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
82+ if (len > maxLength) {
83 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
84 return(NULL);
85 }
86@@ -3338,7 +3344,10 @@ const xmlChar *
87 xmlParseName(xmlParserCtxtPtr ctxt) {
88 const xmlChar *in;
89 const xmlChar *ret;
90- int count = 0;
91+ size_t count = 0;
92+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
93+ XML_MAX_TEXT_LENGTH :
94+ XML_MAX_NAME_LENGTH;
95
96 GROW;
97
98@@ -3362,8 +3371,7 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
99 in++;
100 if ((*in > 0) && (*in < 0x80)) {
101 count = in - ctxt->input->cur;
102- if ((count > XML_MAX_NAME_LENGTH) &&
103- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
104+ if (count > maxLength) {
105 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
106 return(NULL);
107 }
108@@ -3384,6 +3392,9 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
109 int len = 0, l;
110 int c;
111 int count = 0;
112+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
113+ XML_MAX_TEXT_LENGTH :
114+ XML_MAX_NAME_LENGTH;
115 size_t startPosition = 0;
116
117 #ifdef DEBUG
118@@ -3404,17 +3415,13 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
119 while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
120 (xmlIsNameChar(ctxt, c) && (c != ':'))) {
121 if (count++ > XML_PARSER_CHUNK_SIZE) {
122- if ((len > XML_MAX_NAME_LENGTH) &&
123- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
124- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
125- return(NULL);
126- }
127 count = 0;
128 GROW;
129 if (ctxt->instate == XML_PARSER_EOF)
130 return(NULL);
131 }
132- len += l;
133+ if (len <= INT_MAX - l)
134+ len += l;
135 NEXTL(l);
136 c = CUR_CHAR(l);
137 if (c == 0) {
138@@ -3432,8 +3439,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
139 c = CUR_CHAR(l);
140 }
141 }
142- if ((len > XML_MAX_NAME_LENGTH) &&
143- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
144+ if (len > maxLength) {
145 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
146 return(NULL);
147 }
148@@ -3459,7 +3465,10 @@ static const xmlChar *
149 xmlParseNCName(xmlParserCtxtPtr ctxt) {
150 const xmlChar *in, *e;
151 const xmlChar *ret;
152- int count = 0;
153+ size_t count = 0;
154+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
155+ XML_MAX_TEXT_LENGTH :
156+ XML_MAX_NAME_LENGTH;
157
158 #ifdef DEBUG
159 nbParseNCName++;
160@@ -3484,8 +3493,7 @@ xmlParseNCName(xmlParserCtxtPtr ctxt) {
161 goto complex;
162 if ((*in > 0) && (*in < 0x80)) {
163 count = in - ctxt->input->cur;
164- if ((count > XML_MAX_NAME_LENGTH) &&
165- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
166+ if (count > maxLength) {
167 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
168 return(NULL);
169 }
170@@ -3567,6 +3575,9 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
171 const xmlChar *cur = *str;
172 int len = 0, l;
173 int c;
174+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
175+ XML_MAX_TEXT_LENGTH :
176+ XML_MAX_NAME_LENGTH;
177
178 #ifdef DEBUG
179 nbParseStringName++;
180@@ -3602,12 +3613,6 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
181 if (len + 10 > max) {
182 xmlChar *tmp;
183
184- if ((len > XML_MAX_NAME_LENGTH) &&
185- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
186- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
187- xmlFree(buffer);
188- return(NULL);
189- }
190 max *= 2;
191 tmp = (xmlChar *) xmlRealloc(buffer,
192 max * sizeof(xmlChar));
193@@ -3621,14 +3626,18 @@ xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
194 COPY_BUF(l,buffer,len,c);
195 cur += l;
196 c = CUR_SCHAR(cur, l);
197+ if (len > maxLength) {
198+ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
199+ xmlFree(buffer);
200+ return(NULL);
201+ }
202 }
203 buffer[len] = 0;
204 *str = cur;
205 return(buffer);
206 }
207 }
208- if ((len > XML_MAX_NAME_LENGTH) &&
209- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
210+ if (len > maxLength) {
211 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
212 return(NULL);
213 }
214@@ -3655,6 +3664,9 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
215 int len = 0, l;
216 int c;
217 int count = 0;
218+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
219+ XML_MAX_TEXT_LENGTH :
220+ XML_MAX_NAME_LENGTH;
221
222 #ifdef DEBUG
223 nbParseNmToken++;
224@@ -3706,12 +3718,6 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
225 if (len + 10 > max) {
226 xmlChar *tmp;
227
228- if ((max > XML_MAX_NAME_LENGTH) &&
229- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
230- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
231- xmlFree(buffer);
232- return(NULL);
233- }
234 max *= 2;
235 tmp = (xmlChar *) xmlRealloc(buffer,
236 max * sizeof(xmlChar));
237@@ -3725,6 +3731,11 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
238 COPY_BUF(l,buffer,len,c);
239 NEXTL(l);
240 c = CUR_CHAR(l);
241+ if (len > maxLength) {
242+ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
243+ xmlFree(buffer);
244+ return(NULL);
245+ }
246 }
247 buffer[len] = 0;
248 return(buffer);
249@@ -3732,8 +3743,7 @@ xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
250 }
251 if (len == 0)
252 return(NULL);
253- if ((len > XML_MAX_NAME_LENGTH) &&
254- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
255+ if (len > maxLength) {
256 xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
257 return(NULL);
258 }
259@@ -3759,6 +3769,9 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
260 int len = 0;
261 int size = XML_PARSER_BUFFER_SIZE;
262 int c, l;
263+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
264+ XML_MAX_HUGE_LENGTH :
265+ XML_MAX_TEXT_LENGTH;
266 xmlChar stop;
267 xmlChar *ret = NULL;
268 const xmlChar *cur = NULL;
269@@ -3818,6 +3831,12 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
270 GROW;
271 c = CUR_CHAR(l);
272 }
273+
274+ if (len > maxLength) {
275+ xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
276+ "entity value too long\n");
277+ goto error;
278+ }
279 }
280 buf[len] = 0;
281 if (ctxt->instate == XML_PARSER_EOF)
282@@ -3905,6 +3924,9 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
283 xmlChar *rep = NULL;
284 size_t len = 0;
285 size_t buf_size = 0;
286+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
287+ XML_MAX_HUGE_LENGTH :
288+ XML_MAX_TEXT_LENGTH;
289 int c, l, in_space = 0;
290 xmlChar *current = NULL;
291 xmlEntityPtr ent;
292@@ -3925,16 +3925,6 @@
293 while (((NXT(0) != limit) && /* checked */
294 (IS_CHAR(c)) && (c != '<')) &&
295 (ctxt->instate != XML_PARSER_EOF)) {
296- /*
297- * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
298- * special option is given
299- */
300- if ((len > XML_MAX_TEXT_LENGTH) &&
301- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
302- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
303- "AttValue length too long\n");
304- goto mem_error;
305- }
306 if (c == 0) break;
307 if (c == '&') {
308 in_space = 0;
309@@ -4093,6 +4105,11 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
310 }
311 GROW;
312 c = CUR_CHAR(l);
313+ if (len > maxLength) {
314+ xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
315+ "AttValue length too long\n");
316+ goto mem_error;
317+ }
318 }
319 if (ctxt->instate == XML_PARSER_EOF)
320 goto error;
321@@ -4114,16 +4131,6 @@ xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
322 } else
323 NEXT;
324
325- /*
326- * There we potentially risk an overflow, don't allow attribute value of
327- * length more than INT_MAX it is a very reasonable assumption !
328- */
329- if (len >= INT_MAX) {
330- xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
331- "AttValue length too long\n");
332- goto mem_error;
333- }
334-
335 if (attlen != NULL) *attlen = (int) len;
336 return(buf);
337
338@@ -4194,6 +4201,9 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
339 int len = 0;
340 int size = XML_PARSER_BUFFER_SIZE;
341 int cur, l;
342+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
343+ XML_MAX_TEXT_LENGTH :
344+ XML_MAX_NAME_LENGTH;
345 xmlChar stop;
346 int state = ctxt->instate;
347 int count = 0;
348@@ -4221,13 +4231,6 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
349 if (len + 5 >= size) {
350 xmlChar *tmp;
351
352- if ((size > XML_MAX_NAME_LENGTH) &&
353- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
354- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
355- xmlFree(buf);
356- ctxt->instate = (xmlParserInputState) state;
357- return(NULL);
358- }
359 size *= 2;
360 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
361 if (tmp == NULL) {
362@@ -4256,6 +4259,12 @@ xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
363 SHRINK;
364 cur = CUR_CHAR(l);
365 }
366+ if (len > maxLength) {
367+ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
368+ xmlFree(buf);
369+ ctxt->instate = (xmlParserInputState) state;
370+ return(NULL);
371+ }
372 }
373 buf[len] = 0;
374 ctxt->instate = (xmlParserInputState) state;
375@@ -4283,6 +4292,9 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
376 xmlChar *buf = NULL;
377 int len = 0;
378 int size = XML_PARSER_BUFFER_SIZE;
379+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
380+ XML_MAX_TEXT_LENGTH :
381+ XML_MAX_NAME_LENGTH;
382 xmlChar cur;
383 xmlChar stop;
384 int count = 0;
385@@ -4310,12 +4322,6 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
386 if (len + 1 >= size) {
387 xmlChar *tmp;
388
389- if ((size > XML_MAX_NAME_LENGTH) &&
390- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
391- xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
392- xmlFree(buf);
393- return(NULL);
394- }
395 size *= 2;
396 tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
397 if (tmp == NULL) {
398@@ -4343,6 +4349,11 @@ xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
399 SHRINK;
400 cur = CUR;
401 }
402+ if (len > maxLength) {
403+ xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
404+ xmlFree(buf);
405+ return(NULL);
406+ }
407 }
408 buf[len] = 0;
409 if (cur != stop) {
410@@ -4742,6 +4753,9 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
411 int r, rl;
412 int cur, l;
413 size_t count = 0;
414+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
415+ XML_MAX_HUGE_LENGTH :
416+ XML_MAX_TEXT_LENGTH;
417 int inputid;
418
419 inputid = ctxt->input->id;
420@@ -4787,13 +4801,6 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
421 if ((r == '-') && (q == '-')) {
422 xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
423 }
424- if ((len > XML_MAX_TEXT_LENGTH) &&
425- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
426- xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
427- "Comment too big found", NULL);
428- xmlFree (buf);
429- return;
430- }
431 if (len + 5 >= size) {
432 xmlChar *new_buf;
433 size_t new_size;
434@@ -4831,6 +4838,13 @@ xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
435 GROW;
436 cur = CUR_CHAR(l);
437 }
438+
439+ if (len > maxLength) {
440+ xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
441+ "Comment too big found", NULL);
442+ xmlFree (buf);
443+ return;
444+ }
445 }
446 buf[len] = 0;
447 if (cur == 0) {
448@@ -4875,6 +4889,9 @@ xmlParseComment(xmlParserCtxtPtr ctxt) {
449 xmlChar *buf = NULL;
450 size_t size = XML_PARSER_BUFFER_SIZE;
451 size_t len = 0;
452+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
453+ XML_MAX_HUGE_LENGTH :
454+ XML_MAX_TEXT_LENGTH;
455 xmlParserInputState state;
456 const xmlChar *in;
457 size_t nbchar = 0;
458@@ -4958,8 +4975,7 @@ get_more:
459 buf[len] = 0;
460 }
461 }
462- if ((len > XML_MAX_TEXT_LENGTH) &&
463- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
464+ if (len > maxLength) {
465 xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
466 "Comment too big found", NULL);
467 xmlFree (buf);
468@@ -5159,6 +5175,9 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
469 xmlChar *buf = NULL;
470 size_t len = 0;
471 size_t size = XML_PARSER_BUFFER_SIZE;
472+ size_t maxLength = (ctxt->options & XML_PARSE_HUGE) ?
473+ XML_MAX_HUGE_LENGTH :
474+ XML_MAX_TEXT_LENGTH;
475 int cur, l;
476 const xmlChar *target;
477 xmlParserInputState state;
478@@ -5234,14 +5253,6 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
479 return;
480 }
481 count = 0;
482- if ((len > XML_MAX_TEXT_LENGTH) &&
483- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
484- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
485- "PI %s too big found", target);
486- xmlFree(buf);
487- ctxt->instate = state;
488- return;
489- }
490 }
491 COPY_BUF(l,buf,len,cur);
492 NEXTL(l);
493@@ -5251,15 +5262,14 @@ xmlParsePI(xmlParserCtxtPtr ctxt) {
494 GROW;
495 cur = CUR_CHAR(l);
496 }
497+ if (len > maxLength) {
498+ xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
499+ "PI %s too big found", target);
500+ xmlFree(buf);
501+ ctxt->instate = state;
502+ return;
503+ }
504 }
505- if ((len > XML_MAX_TEXT_LENGTH) &&
506- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
507- xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
508- "PI %s too big found", target);
509- xmlFree(buf);
510- ctxt->instate = state;
511- return;
512- }
513 buf[len] = 0;
514 if (cur != '?') {
515 xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
516@@ -8954,6 +8964,9 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
517 const xmlChar *in = NULL, *start, *end, *last;
518 xmlChar *ret = NULL;
519 int line, col;
520+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
521+ XML_MAX_HUGE_LENGTH :
522+ XML_MAX_TEXT_LENGTH;
523
524 GROW;
525 in = (xmlChar *) CUR_PTR;
526@@ -8993,8 +9006,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
527 start = in;
528 if (in >= end) {
529 GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
530- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
531- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
532+ if ((in - start) > maxLength) {
533 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
534 "AttValue length too long\n");
535 return(NULL);
536@@ -9007,8 +9019,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
537 if ((*in++ == 0x20) && (*in == 0x20)) break;
538 if (in >= end) {
539 GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
540- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
541- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
542+ if ((in - start) > maxLength) {
543 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
544 "AttValue length too long\n");
545 return(NULL);
546@@ -9041,16 +9052,14 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
547 last = last + delta;
548 }
549 end = ctxt->input->end;
550- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
551- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
552+ if ((in - start) > maxLength) {
553 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
554 "AttValue length too long\n");
555 return(NULL);
556 }
557 }
558 }
559- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
560- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
561+ if ((in - start) > maxLength) {
562 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
563 "AttValue length too long\n");
564 return(NULL);
565@@ -9063,8 +9072,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
566 col++;
567 if (in >= end) {
568 GROW_PARSE_ATT_VALUE_INTERNAL(ctxt, in, start, end)
569- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
570- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
571+ if ((in - start) > maxLength) {
572 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
573 "AttValue length too long\n");
574 return(NULL);
575@@ -9072,8 +9080,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
576 }
577 }
578 last = in;
579- if (((in - start) > XML_MAX_TEXT_LENGTH) &&
580- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
581+ if ((in - start) > maxLength) {
582 xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
583 "AttValue length too long\n");
584 return(NULL);
585@@ -9763,6 +9770,9 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
586 int s, sl;
587 int cur, l;
588 int count = 0;
589+ int maxLength = (ctxt->options & XML_PARSE_HUGE) ?
590+ XML_MAX_HUGE_LENGTH :
591+ XML_MAX_TEXT_LENGTH;
592
593 /* Check 2.6.0 was NXT(0) not RAW */
594 if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
595@@ -9796,13 +9806,6 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
596 if (len + 5 >= size) {
597 xmlChar *tmp;
598
599- if ((size > XML_MAX_TEXT_LENGTH) &&
600- ((ctxt->options & XML_PARSE_HUGE) == 0)) {
601- xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
602- "CData section too big found", NULL);
603- xmlFree (buf);
604- return;
605- }
606 tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
607 if (tmp == NULL) {
608 xmlFree(buf);
609@@ -9829,6 +9832,12 @@ xmlParseCDSect(xmlParserCtxtPtr ctxt) {
610 }
611 NEXTL(l);
612 cur = CUR_CHAR(l);
613+ if (len > maxLength) {
614+ xmlFatalErrMsg(ctxt, XML_ERR_CDATA_NOT_FINISHED,
615+ "CData section too big found\n");
616+ xmlFree(buf);
617+ return;
618+ }
619 }
620 buf[len] = 0;
621 ctxt->instate = XML_PARSER_CONTENT;
622--
623GitLab
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch
new file mode 100644
index 0000000000..c19726fe9f
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-40304.patch
@@ -0,0 +1,104 @@
1From 1b41ec4e9433b05bb0376be4725804c54ef1d80b Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 31 Aug 2022 22:11:25 +0200
4Subject: [PATCH] [CVE-2022-40304] Fix dict corruption caused by entity
5 reference cycles
6
7When an entity reference cycle is detected, the entity content is
8cleared by setting its first byte to zero. But the entity content might
9be allocated from a dict. In this case, the dict entry becomes corrupted
10leading to all kinds of logic errors, including memory errors like
11double-frees.
12
13Stop storing entity content, orig, ExternalID and SystemID in a dict.
14These values are unlikely to occur multiple times in a document, so they
15shouldn't have been stored in a dict in the first place.
16
17Thanks to Ned Williamson and Nathan Wachholz working with Google Project
18Zero for the report!
19
20CVE: CVE-2022-40304
21Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/1b41ec4e9433b05bb0376be4725804c54ef1d80b]
22Signed-off-by: Bhabu Bindu <bhabu.bindu@kpit.com>
23---
24 entities.c | 55 ++++++++++++++++--------------------------------------
25 1 file changed, 16 insertions(+), 39 deletions(-)
26
27diff --git a/entities.c b/entities.c
28index 84435515..d4e5412e 100644
29--- a/entities.c
30+++ b/entities.c
31@@ -128,36 +128,19 @@ xmlFreeEntity(xmlEntityPtr entity)
32 if ((entity->children) && (entity->owner == 1) &&
33 (entity == (xmlEntityPtr) entity->children->parent))
34 xmlFreeNodeList(entity->children);
35- if (dict != NULL) {
36- if ((entity->name != NULL) && (!xmlDictOwns(dict, entity->name)))
37- xmlFree((char *) entity->name);
38- if ((entity->ExternalID != NULL) &&
39- (!xmlDictOwns(dict, entity->ExternalID)))
40- xmlFree((char *) entity->ExternalID);
41- if ((entity->SystemID != NULL) &&
42- (!xmlDictOwns(dict, entity->SystemID)))
43- xmlFree((char *) entity->SystemID);
44- if ((entity->URI != NULL) && (!xmlDictOwns(dict, entity->URI)))
45- xmlFree((char *) entity->URI);
46- if ((entity->content != NULL)
47- && (!xmlDictOwns(dict, entity->content)))
48- xmlFree((char *) entity->content);
49- if ((entity->orig != NULL) && (!xmlDictOwns(dict, entity->orig)))
50- xmlFree((char *) entity->orig);
51- } else {
52- if (entity->name != NULL)
53- xmlFree((char *) entity->name);
54- if (entity->ExternalID != NULL)
55- xmlFree((char *) entity->ExternalID);
56- if (entity->SystemID != NULL)
57- xmlFree((char *) entity->SystemID);
58- if (entity->URI != NULL)
59- xmlFree((char *) entity->URI);
60- if (entity->content != NULL)
61- xmlFree((char *) entity->content);
62- if (entity->orig != NULL)
63- xmlFree((char *) entity->orig);
64- }
65+ if ((entity->name != NULL) &&
66+ ((dict == NULL) || (!xmlDictOwns(dict, entity->name))))
67+ xmlFree((char *) entity->name);
68+ if (entity->ExternalID != NULL)
69+ xmlFree((char *) entity->ExternalID);
70+ if (entity->SystemID != NULL)
71+ xmlFree((char *) entity->SystemID);
72+ if (entity->URI != NULL)
73+ xmlFree((char *) entity->URI);
74+ if (entity->content != NULL)
75+ xmlFree((char *) entity->content);
76+ if (entity->orig != NULL)
77+ xmlFree((char *) entity->orig);
78 xmlFree(entity);
79 }
80
81@@ -193,18 +176,12 @@ xmlCreateEntity(xmlDictPtr dict, const xmlChar *name, int type,
82 ret->SystemID = xmlStrdup(SystemID);
83 } else {
84 ret->name = xmlDictLookup(dict, name, -1);
85- if (ExternalID != NULL)
86- ret->ExternalID = xmlDictLookup(dict, ExternalID, -1);
87- if (SystemID != NULL)
88- ret->SystemID = xmlDictLookup(dict, SystemID, -1);
89+ ret->ExternalID = xmlStrdup(ExternalID);
90+ ret->SystemID = xmlStrdup(SystemID);
91 }
92 if (content != NULL) {
93 ret->length = xmlStrlen(content);
94- if ((dict != NULL) && (ret->length < 5))
95- ret->content = (xmlChar *)
96- xmlDictLookup(dict, content, ret->length);
97- else
98- ret->content = xmlStrndup(content, ret->length);
99+ ret->content = xmlStrndup(content, ret->length);
100 } else {
101 ret->length = 0;
102 ret->content = NULL;
103--
104GitLab
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch
new file mode 100644
index 0000000000..907f2c4d47
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-28484.patch
@@ -0,0 +1,79 @@
1From e4f85f1bd2eb34d9b49da9154a4cc3a1bc284f68 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Fri, 7 Apr 2023 11:46:35 +0200
4Subject: [PATCH] [CVE-2023-28484] Fix null deref in xmlSchemaFixupComplexType
5
6Fix a null pointer dereference when parsing (invalid) XML schemas.
7
8Thanks to Robby Simpson for the report!
9
10Fixes #491.
11
12CVE: CVE-2023-28484
13Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/e4f85f1bd2eb34d9b49da9154a4cc3a1bc284f68]
14
15Signed-off-by: Peter Marko <peter.marko@siemens.com>
16---
17 result/schemas/issue491_0_0.err | 1 +
18 test/schemas/issue491_0.xml | 1 +
19 test/schemas/issue491_0.xsd | 18 ++++++++++++++++++
20 xmlschemas.c | 2 +-
21 4 files changed, 21 insertions(+), 1 deletion(-)
22 create mode 100644 result/schemas/issue491_0_0.err
23 create mode 100644 test/schemas/issue491_0.xml
24 create mode 100644 test/schemas/issue491_0.xsd
25
26diff --git a/result/schemas/issue491_0_0.err b/result/schemas/issue491_0_0.err
27new file mode 100644
28index 00000000..9b2bb969
29--- /dev/null
30+++ b/result/schemas/issue491_0_0.err
31@@ -0,0 +1 @@
32+./test/schemas/issue491_0.xsd:8: element complexType: Schemas parser error : complex type 'ChildType': The content type of both, the type and its base type, must either 'mixed' or 'element-only'.
33diff --git a/test/schemas/issue491_0.xml b/test/schemas/issue491_0.xml
34new file mode 100644
35index 00000000..e2b2fc2e
36--- /dev/null
37+++ b/test/schemas/issue491_0.xml
38@@ -0,0 +1 @@
39+<Child xmlns="http://www.test.com">5</Child>
40diff --git a/test/schemas/issue491_0.xsd b/test/schemas/issue491_0.xsd
41new file mode 100644
42index 00000000..81702649
43--- /dev/null
44+++ b/test/schemas/issue491_0.xsd
45@@ -0,0 +1,18 @@
46+<?xml version='1.0' encoding='UTF-8'?>
47+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.test.com" targetNamespace="http://www.test.com" elementFormDefault="qualified" attributeFormDefault="unqualified">
48+ <xs:complexType name="BaseType">
49+ <xs:simpleContent>
50+ <xs:extension base="xs:int" />
51+ </xs:simpleContent>
52+ </xs:complexType>
53+ <xs:complexType name="ChildType">
54+ <xs:complexContent>
55+ <xs:extension base="BaseType">
56+ <xs:sequence>
57+ <xs:element name="bad" type="xs:int" minOccurs="0" maxOccurs="1"/>
58+ </xs:sequence>
59+ </xs:extension>
60+ </xs:complexContent>
61+ </xs:complexType>
62+ <xs:element name="Child" type="ChildType" />
63+</xs:schema>
64diff --git a/xmlschemas.c b/xmlschemas.c
65index 6a353858..a4eaf591 100644
66--- a/xmlschemas.c
67+++ b/xmlschemas.c
68@@ -18632,7 +18632,7 @@ xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
69 "allowed to appear inside other model groups",
70 NULL, NULL);
71
72- } else if (! dummySequence) {
73+ } else if ((!dummySequence) && (baseType->subtypes != NULL)) {
74 xmlSchemaTreeItemPtr effectiveContent =
75 (xmlSchemaTreeItemPtr) type->subtypes;
76 /*
77--
78GitLab
79
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch
new file mode 100644
index 0000000000..1252668577
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-29469.patch
@@ -0,0 +1,42 @@
1From 547edbf1cbdccd46b2e8ff322a456eaa5931c5df Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Fri, 7 Apr 2023 11:49:27 +0200
4Subject: [PATCH] [CVE-2023-29469] Hashing of empty dict strings isn't
5 deterministic
6
7When hashing empty strings which aren't null-terminated,
8xmlDictComputeFastKey could produce inconsistent results. This could
9lead to various logic or memory errors, including double frees.
10
11For consistency the seed is also taken into account, but this shouldn't
12have an impact on security.
13
14Found by OSS-Fuzz.
15
16Fixes #510.
17
18CVE: CVE-2023-29469
19Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/547edbf1cbdccd46b2e8ff322a456eaa5931c5df]
20
21Signed-off-by: Peter Marko <peter.marko@siemens.com>
22---
23 dict.c | 3 ++-
24 1 file changed, 2 insertions(+), 1 deletion(-)
25
26diff --git a/dict.c b/dict.c
27index 86c3f6d7..d7fd1a06 100644
28--- a/dict.c
29+++ b/dict.c
30@@ -451,7 +451,8 @@ static unsigned long
31 xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
32 unsigned long value = seed;
33
34- if (name == NULL) return(0);
35+ if ((name == NULL) || (namelen <= 0))
36+ return(value);
37 value = *name;
38 value <<= 5;
39 if (namelen > 10) {
40--
41GitLab
42
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch
new file mode 100644
index 0000000000..9689cec67d
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch
@@ -0,0 +1,36 @@
1From d0c3f01e110d54415611c5fa0040cdf4a56053f9 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Sat, 6 May 2023 17:47:37 +0200
4Subject: [PATCH] parser: Fix old SAX1 parser with custom callbacks
5
6For some reason, xmlCtxtUseOptionsInternal set the start and end element
7SAX handlers to the internal DOM builder functions when XML_PARSE_SAX1
8was specified. This means that custom SAX handlers could never work with
9that flag because these functions would receive the wrong user data
10argument and crash immediately.
11
12Fixes #535.
13
14Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/d0c3f01e110d54415611c5fa0040cdf4a56053f9]
15CVE: CVE-2023-39615
16Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
17---
18 parser.c | 2 --
19 1 file changed, 2 deletions(-)
20
21diff --git a/parser.c b/parser.c
22index 6e09208..7814e6e 100644
23--- a/parser.c
24+++ b/parser.c
25@@ -15156,8 +15156,6 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
26 }
27 #ifdef LIBXML_SAX1_ENABLED
28 if (options & XML_PARSE_SAX1) {
29- ctxt->sax->startElement = xmlSAX2StartElement;
30- ctxt->sax->endElement = xmlSAX2EndElement;
31 ctxt->sax->startElementNs = NULL;
32 ctxt->sax->endElementNs = NULL;
33 ctxt->sax->initialized = 1;
34--
352.24.4
36
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch
new file mode 100644
index 0000000000..ebd9868fac
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch
@@ -0,0 +1,71 @@
1From 235b15a590eecf97b09e87bdb7e4f8333e9de129 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Mon, 8 May 2023 17:58:02 +0200
4Subject: [PATCH] SAX: Always initialize SAX1 element handlers
5
6Follow-up to commit d0c3f01e. A parser context will be initialized to
7SAX version 2, but this can be overridden with XML_PARSE_SAX1 later,
8so we must initialize the SAX1 element handlers as well.
9
10Change the check in xmlDetectSAX2 to only look for XML_SAX2_MAGIC, so
11we don't switch to SAX1 if the SAX2 element handlers are NULL.
12
13Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/235b15a590eecf97b09e87bdb7e4f8333e9de129]
14CVE: CVE-2023-39615
15Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
16---
17 SAX2.c | 11 +++++++----
18 parser.c | 5 +----
19 2 files changed, 8 insertions(+), 8 deletions(-)
20
21diff --git a/SAX2.c b/SAX2.c
22index 5f141f9..902d34d 100644
23--- a/SAX2.c
24+++ b/SAX2.c
25@@ -2869,20 +2869,23 @@ xmlSAXVersion(xmlSAXHandler *hdlr, int version)
26 {
27 if (hdlr == NULL) return(-1);
28 if (version == 2) {
29- hdlr->startElement = NULL;
30- hdlr->endElement = NULL;
31 hdlr->startElementNs = xmlSAX2StartElementNs;
32 hdlr->endElementNs = xmlSAX2EndElementNs;
33 hdlr->serror = NULL;
34 hdlr->initialized = XML_SAX2_MAGIC;
35 #ifdef LIBXML_SAX1_ENABLED
36 } else if (version == 1) {
37- hdlr->startElement = xmlSAX2StartElement;
38- hdlr->endElement = xmlSAX2EndElement;
39 hdlr->initialized = 1;
40 #endif /* LIBXML_SAX1_ENABLED */
41 } else
42 return(-1);
43+#ifdef LIBXML_SAX1_ENABLED
44+ hdlr->startElement = xmlSAX2StartElement;
45+ hdlr->endElement = xmlSAX2EndElement;
46+#else
47+ hdlr->startElement = NULL;
48+ hdlr->endElement = NULL;
49+#endif /* LIBXML_SAX1_ENABLED */
50 hdlr->internalSubset = xmlSAX2InternalSubset;
51 hdlr->externalSubset = xmlSAX2ExternalSubset;
52 hdlr->isStandalone = xmlSAX2IsStandalone;
53diff --git a/parser.c b/parser.c
54index 7814e6e..cf0fb38 100644
55--- a/parser.c
56+++ b/parser.c
57@@ -1102,10 +1102,7 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
58 if (ctxt == NULL) return;
59 sax = ctxt->sax;
60 #ifdef LIBXML_SAX1_ENABLED
61- if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
62- ((sax->startElementNs != NULL) ||
63- (sax->endElementNs != NULL) ||
64- ((sax->startElement == NULL) && (sax->endElement == NULL))))
65+ if ((sax) && (sax->initialized == XML_SAX2_MAGIC))
66 ctxt->sax2 = 1;
67 #else
68 ctxt->sax2 = 1;
69--
702.24.4
71
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch
new file mode 100644
index 0000000000..b177cdaba0
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch
@@ -0,0 +1,44 @@
1From 99fc048d7f7292c5ee18e44c400bd73bc63a47ed Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Fri, 14 Aug 2020 14:18:50 +0200
4Subject: [PATCH] Don't use SAX1 if all element handlers are NULL
5
6Running xmllint with "--sax --noout" installs a SAX2 handler with all
7callbacks set to NULL. In this case or similar situations, we don't want
8to switch to SAX1 parsing.
9
10Note: This patch is needed for "CVE-2023-39615-0002" patch to apply.
11Without this patch the build will fail with undefined sax error.
12
13Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/99fc048d7f7292c5ee18e44c400bd73bc63a47ed]
14Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
15---
16 parser.c | 10 +++++++---
17 1 file changed, 7 insertions(+), 3 deletions(-)
18
19diff --git a/parser.c b/parser.c
20index bb677b0..6e09208 100644
21--- a/parser.c
22+++ b/parser.c
23@@ -1098,11 +1098,15 @@ xmlHasFeature(xmlFeature feature)
24 */
25 static void
26 xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
27+ xmlSAXHandlerPtr sax;
28 if (ctxt == NULL) return;
29+ sax = ctxt->sax;
30 #ifdef LIBXML_SAX1_ENABLED
31- if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
32- ((ctxt->sax->startElementNs != NULL) ||
33- (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
34+ if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
35+ ((sax->startElementNs != NULL) ||
36+ (sax->endElementNs != NULL) ||
37+ ((sax->startElement == NULL) && (sax->endElement == NULL))))
38+ ctxt->sax2 = 1;
39 #else
40 ctxt->sax2 = 1;
41 #endif /* LIBXML_SAX1_ENABLED */
42--
432.24.4
44
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch
new file mode 100644
index 0000000000..182bb29abd
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-1.patch
@@ -0,0 +1,50 @@
1From a22bd982bf10291deea8ba0c61bf75b898c604ce Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 2 Nov 2022 15:44:42 +0100
4Subject: [PATCH] malloc-fail: Fix memory leak in xmlStaticCopyNodeList
5
6Found with libFuzzer, see #344.
7
8Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/a22bd982bf10291deea8ba0c61bf75b898c604ce]
9
10Signed-off-by: Peter Marko <peter.marko@siemens.com>
11Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
12---
13 tree.c | 7 +++++--
14 1 file changed, 5 insertions(+), 2 deletions(-)
15
16diff --git a/tree.c b/tree.c
17index 507869efe..647288ce3 100644
18--- a/tree.c
19+++ b/tree.c
20@@ -4461,7 +4461,7 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
21 }
22 if (doc->intSubset == NULL) {
23 q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
24- if (q == NULL) return(NULL);
25+ if (q == NULL) goto error;
26 q->doc = doc;
27 q->parent = parent;
28 doc->intSubset = (xmlDtdPtr) q;
29@@ -4473,7 +4473,7 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
30 } else
31 #endif /* LIBXML_TREE_ENABLED */
32 q = xmlStaticCopyNode(node, doc, parent, 1);
33- if (q == NULL) return(NULL);
34+ if (q == NULL) goto error;
35 if (ret == NULL) {
36 q->prev = NULL;
37 ret = p = q;
38@@ -4486,6 +4486,9 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
39 node = node->next;
40 }
41 return(ret);
42+error:
43+ xmlFreeNodeList(ret);
44+ return(NULL);
45 }
46
47 /**
48--
49GitLab
50
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch
new file mode 100644
index 0000000000..c7e9681e6a
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2023-45322-2.patch
@@ -0,0 +1,80 @@
1From d39f78069dff496ec865c73aa44d7110e429bce9 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Wed, 23 Aug 2023 20:24:24 +0200
4Subject: [PATCH] tree: Fix copying of DTDs
5
6- Don't create multiple DTD nodes.
7- Fix UAF if malloc fails.
8- Skip DTD nodes if tree module is disabled.
9
10Fixes #583.
11
12CVE: CVE-2023-45322
13Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/d39f78069dff496ec865c73aa44d7110e429bce9]
14
15Signed-off-by: Peter Marko <peter.marko@siemens.com>
16Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
17---
18 tree.c | 31 ++++++++++++++++---------------
19 1 file changed, 16 insertions(+), 15 deletions(-)
20
21diff --git a/tree.c b/tree.c
22index 6c8a875b9..02c1b5791 100644
23--- a/tree.c
24+++ b/tree.c
25@@ -4471,29 +4471,28 @@ xmlNodePtr
26 xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
27 xmlNodePtr ret = NULL;
28 xmlNodePtr p = NULL,q;
29+ xmlDtdPtr newSubset = NULL;
30
31 while (node != NULL) {
32-#ifdef LIBXML_TREE_ENABLED
33 if (node->type == XML_DTD_NODE ) {
34- if (doc == NULL) {
35+#ifdef LIBXML_TREE_ENABLED
36+ if ((doc == NULL) || (doc->intSubset != NULL)) {
37 node = node->next;
38 continue;
39 }
40- if (doc->intSubset == NULL) {
41- q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
42- if (q == NULL) goto error;
43- q->doc = doc;
44- q->parent = parent;
45- doc->intSubset = (xmlDtdPtr) q;
46- xmlAddChild(parent, q);
47- } else {
48- q = (xmlNodePtr) doc->intSubset;
49- xmlAddChild(parent, q);
50- }
51- } else
52+ q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node );
53+ if (q == NULL) goto error;
54+ q->doc = doc;
55+ q->parent = parent;
56+ newSubset = (xmlDtdPtr) q;
57+#else
58+ node = node->next;
59+ continue;
60 #endif /* LIBXML_TREE_ENABLED */
61+ } else {
62 q = xmlStaticCopyNode(node, doc, parent, 1);
63- if (q == NULL) goto error;
64+ if (q == NULL) goto error;
65+ }
66 if (ret == NULL) {
67 q->prev = NULL;
68 ret = p = q;
69@@ -4505,6 +4504,8 @@ xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) {
70 }
71 node = node->next;
72 }
73+ if (newSubset != NULL)
74+ doc->intSubset = newSubset;
75 return(ret);
76 error:
77 xmlFreeNodeList(ret);
78--
79GitLab
80
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch b/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch
new file mode 100644
index 0000000000..31183399f8
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2024-25062-pre1.patch
@@ -0,0 +1,38 @@
1From 31c6ce3b63f8a494ad9e31ca65187a73d8ad3508 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Mon, 9 Nov 2020 17:55:44 +0100
4Subject: [PATCH] Avoid call stack overflow with XML reader and recursive
5 XIncludes
6
7Don't process XIncludes in the result of another inclusion to avoid
8infinite recursion resulting in a call stack overflow.
9
10This is something the XInclude engine shouldn't allow but correct
11handling of intra-document includes would require major changes.
12
13Found by OSS-Fuzz.
14
15Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/31c6ce3b63f8a494ad9e31ca65187a73d8ad3508]
16CVE: CVE-2024-25062 #Dependency Patch
17Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
18---
19 xmlreader.c | 3 ++-
20 1 file changed, 2 insertions(+), 1 deletion(-)
21
22diff --git a/xmlreader.c b/xmlreader.c
23index 01adf74f4..72e40b032 100644
24--- a/xmlreader.c
25+++ b/xmlreader.c
26@@ -1585,7 +1585,8 @@ node_found:
27 /*
28 * Handle XInclude if asked for
29 */
30- if ((reader->xinclude) && (reader->node != NULL) &&
31+ if ((reader->xinclude) && (reader->in_xinclude == 0) &&
32+ (reader->node != NULL) &&
33 (reader->node->type == XML_ELEMENT_NODE) &&
34 (reader->node->ns != NULL) &&
35 ((xmlStrEqual(reader->node->ns->href, XINCLUDE_NS)) ||
36--
37GitLab
38
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch b/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch
new file mode 100644
index 0000000000..5365d5546a
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2024-25062.patch
@@ -0,0 +1,33 @@
1From 2b0aac140d739905c7848a42efc60bfe783a39b7 Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Sat, 14 Oct 2023 22:45:54 +0200
4Subject: [PATCH] [CVE-2024-25062] xmlreader: Don't expand XIncludes when
5 backtracking
6
7Fixes a use-after-free if XML Reader if used with DTD validation and
8XInclude expansion.
9
10Fixes #604.
11
12Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxml2/-/commit/2b0aac140d739905c7848a42efc60bfe783a39b7]
13CVE: CVE-2024-25062
14Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
15---
16 xmlreader.c | 1 +
17 1 file changed, 1 insertion(+)
18
19diff --git a/xmlreader.c b/xmlreader.c
20index 979385a13..fefd68e0b 100644
21--- a/xmlreader.c
22+++ b/xmlreader.c
23@@ -1443,6 +1443,7 @@ node_found:
24 * Handle XInclude if asked for
25 */
26 if ((reader->xinclude) && (reader->in_xinclude == 0) &&
27+ (reader->state != XML_TEXTREADER_BACKTRACK) &&
28 (reader->node != NULL) &&
29 (reader->node->type == XML_ELEMENT_NODE) &&
30 (reader->node->ns != NULL) &&
31--
32GitLab
33
diff --git a/meta/recipes-core/libxml/libxml2/runtest.patch b/meta/recipes-core/libxml/libxml2/runtest.patch
index 0dbb353c0f..c7a90cd3dc 100644
--- a/meta/recipes-core/libxml/libxml2/runtest.patch
+++ b/meta/recipes-core/libxml/libxml2/runtest.patch
@@ -1,28 +1,33 @@
1Add 'install-ptest' rule. Print a standard result line for 1From 6172ccd1e74bc181f5298f19e240234e12876abe Mon Sep 17 00:00:00 2001
2each test. 2From: Tony Tascioglu <tony.tascioglu@windriver.com>
3Date: Tue, 11 May 2021 11:57:46 -0400
4Subject: [PATCH] Add 'install-ptest' rule.
5
6Print a standard result line for each test.
3 7
4Signed-off-by: Mihaela Sendrea <mihaela.sendrea@enea.com> 8Signed-off-by: Mihaela Sendrea <mihaela.sendrea@enea.com>
5Signed-off-by: Andrej Valek <andrej.valek@siemens.com> 9Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
6Upstream-Status: Backport 10Upstream-Status: Pending
7 11
8Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> 12Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
13Signed-off-by: Tony Tascioglu <tony.tascioglu@windriver.com>
9--- 14---
10 Makefile.am | 9 ++++ 15 Makefile.am | 9 +++
11 runsuite.c | 1 + 16 runsuite.c | 1 +
12 runtest.c | 2 + 17 runtest.c | 2 +
13 runxmlconf.c | 1 + 18 runxmlconf.c | 1 +
14 testapi.c | 122 ++++++++++++++++++++++++++++++--------------- 19 testapi.c | 122 ++++++++++++++++++++++++++-------------
15 testchar.c | 156 +++++++++++++++++++++++++++++++++++++++++----------------- 20 testchar.c | 156 +++++++++++++++++++++++++++++++++++---------------
16 testdict.c | 1 + 21 testdict.c | 1 +
17 testlimits.c | 1 + 22 testlimits.c | 1 +
18 testrecurse.c | 2 + 23 testrecurse.c | 2 +
19 9 files changed, 210 insertions(+), 85 deletions(-) 24 9 files changed, 210 insertions(+), 85 deletions(-)
20 25
21diff --git a/Makefile.am b/Makefile.am 26diff --git a/Makefile.am b/Makefile.am
22index 9c630be..7cfd04b 100644 27index 05d1671f..ae622745 100644
23--- a/Makefile.am 28--- a/Makefile.am
24+++ b/Makefile.am 29+++ b/Makefile.am
25@@ -202,6 +202,15 @@ runxmlconf_LDADD= $(LDADDS) 30@@ -198,6 +198,15 @@ runxmlconf_LDADD= $(LDADDS)
26 #testOOM_DEPENDENCIES = $(DEPS) 31 #testOOM_DEPENDENCIES = $(DEPS)
27 #testOOM_LDADD= $(LDADDS) 32 #testOOM_LDADD= $(LDADDS)
28 33
@@ -39,10 +44,10 @@ index 9c630be..7cfd04b 100644
39 testchar$(EXEEXT) testdict$(EXEEXT) runxmlconf$(EXEEXT) 44 testchar$(EXEEXT) testdict$(EXEEXT) runxmlconf$(EXEEXT)
40 [ -d test ] || $(LN_S) $(srcdir)/test . 45 [ -d test ] || $(LN_S) $(srcdir)/test .
41diff --git a/runsuite.c b/runsuite.c 46diff --git a/runsuite.c b/runsuite.c
42index aaab13e..9ba2c5d 100644 47index d24b5ec3..f7ff2521 100644
43--- a/runsuite.c 48--- a/runsuite.c
44+++ b/runsuite.c 49+++ b/runsuite.c
45@@ -1162,6 +1162,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 50@@ -1147,6 +1147,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
46 51
47 if (logfile != NULL) 52 if (logfile != NULL)
48 fclose(logfile); 53 fclose(logfile);
@@ -51,10 +56,10 @@ index aaab13e..9ba2c5d 100644
51 } 56 }
52 #else /* !SCHEMAS */ 57 #else /* !SCHEMAS */
53diff --git a/runtest.c b/runtest.c 58diff --git a/runtest.c b/runtest.c
54index addda5c..8ba5d59 100644 59index ffa98d04..470f95cb 100644
55--- a/runtest.c 60--- a/runtest.c
56+++ b/runtest.c 61+++ b/runtest.c
57@@ -4501,6 +4501,7 @@ launchTests(testDescPtr tst) { 62@@ -4508,6 +4508,7 @@ launchTests(testDescPtr tst) {
58 xmlCharEncCloseFunc(ebcdicHandler); 63 xmlCharEncCloseFunc(ebcdicHandler);
59 xmlCharEncCloseFunc(eucJpHandler); 64 xmlCharEncCloseFunc(eucJpHandler);
60 65
@@ -62,7 +67,7 @@ index addda5c..8ba5d59 100644
62 return(err); 67 return(err);
63 } 68 }
64 69
65@@ -4577,6 +4578,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 70@@ -4588,6 +4589,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
66 xmlCleanupParser(); 71 xmlCleanupParser();
67 xmlMemoryDump(); 72 xmlMemoryDump();
68 73
@@ -71,7 +76,7 @@ index addda5c..8ba5d59 100644
71 } 76 }
72 77
73diff --git a/runxmlconf.c b/runxmlconf.c 78diff --git a/runxmlconf.c b/runxmlconf.c
74index cef20f4..4f291fb 100644 79index 70f61017..e882b3a1 100644
75--- a/runxmlconf.c 80--- a/runxmlconf.c
76+++ b/runxmlconf.c 81+++ b/runxmlconf.c
77@@ -595,6 +595,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 82@@ -595,6 +595,7 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
@@ -83,7 +88,7 @@ index cef20f4..4f291fb 100644
83 } 88 }
84 89
85diff --git a/testapi.c b/testapi.c 90diff --git a/testapi.c b/testapi.c
86index 4a751e2..7ccc066 100644 91index ff8b470d..52b51d78 100644
87--- a/testapi.c 92--- a/testapi.c
88+++ b/testapi.c 93+++ b/testapi.c
89@@ -1246,49 +1246,91 @@ static int 94@@ -1246,49 +1246,91 @@ static int
@@ -219,7 +224,7 @@ index 4a751e2..7ccc066 100644
219 } 224 }
220 225
221diff --git a/testchar.c b/testchar.c 226diff --git a/testchar.c b/testchar.c
222index 0d08792..f555d3b 100644 227index 6866a175..7bce0132 100644
223--- a/testchar.c 228--- a/testchar.c
224+++ b/testchar.c 229+++ b/testchar.c
225@@ -23,7 +23,7 @@ static void errorHandler(void *unused, xmlErrorPtr err) { 230@@ -23,7 +23,7 @@ static void errorHandler(void *unused, xmlErrorPtr err) {
@@ -797,7 +802,7 @@ index 0d08792..f555d3b 100644
797 /* 802 /*
798 * Cleanup function for the XML library. 803 * Cleanup function for the XML library.
799diff --git a/testdict.c b/testdict.c 804diff --git a/testdict.c b/testdict.c
800index 40bebd0..114b934 100644 805index 40bebd05..114b9347 100644
801--- a/testdict.c 806--- a/testdict.c
802+++ b/testdict.c 807+++ b/testdict.c
803@@ -440,5 +440,6 @@ int main(void) 808@@ -440,5 +440,6 @@ int main(void)
@@ -808,7 +813,7 @@ index 40bebd0..114b934 100644
808 return(ret); 813 return(ret);
809 } 814 }
810diff --git a/testlimits.c b/testlimits.c 815diff --git a/testlimits.c b/testlimits.c
811index 68c94db..1584434 100644 816index 059116a6..f0bee68d 100644
812--- a/testlimits.c 817--- a/testlimits.c
813+++ b/testlimits.c 818+++ b/testlimits.c
814@@ -1634,5 +1634,6 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { 819@@ -1634,5 +1634,6 @@ main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) {
@@ -819,7 +824,7 @@ index 68c94db..1584434 100644
819 return(ret); 824 return(ret);
820 } 825 }
821diff --git a/testrecurse.c b/testrecurse.c 826diff --git a/testrecurse.c b/testrecurse.c
822index f95ae1c..74c8f8b 100644 827index 0cbe25a6..3ecadb40 100644
823--- a/testrecurse.c 828--- a/testrecurse.c
824+++ b/testrecurse.c 829+++ b/testrecurse.c
825@@ -892,6 +892,7 @@ launchTests(testDescPtr tst) { 830@@ -892,6 +892,7 @@ launchTests(testDescPtr tst) {
@@ -838,5 +843,5 @@ index f95ae1c..74c8f8b 100644
838 return(ret); 843 return(ret);
839 } 844 }
840-- 845--
8412.7.4 8462.25.1
842 847
diff --git a/meta/recipes-core/libxml/libxml2_2.9.10.bb b/meta/recipes-core/libxml/libxml2_2.9.10.bb
index 4ebfb9e556..72f830b6d3 100644
--- a/meta/recipes-core/libxml/libxml2_2.9.10.bb
+++ b/meta/recipes-core/libxml/libxml2_2.9.10.bb
@@ -1,6 +1,6 @@
1SUMMARY = "XML C Parser Library and Toolkit" 1SUMMARY = "XML C Parser Library and Toolkit"
2DESCRIPTION = "The XML Parser Library allows for manipulation of XML files. Libxml2 exports Push and Pull type parser interfaces for both XML and HTML. It can do DTD validation at parse time, on a parsed document instance or with an arbitrary DTD. Libxml2 includes complete XPath, XPointer and Xinclude implementations. It also has a SAX like interface, which is designed to be compatible with Expat." 2DESCRIPTION = "The XML Parser Library allows for manipulation of XML files. Libxml2 exports Push and Pull type parser interfaces for both XML and HTML. It can do DTD validation at parse time, on a parsed document instance or with an arbitrary DTD. Libxml2 includes complete XPath, XPointer and Xinclude implementations. It also has a SAX like interface, which is designed to be compatible with Expat."
3HOMEPAGE = "http://www.xmlsoft.org/" 3HOMEPAGE = "https://gitlab.gnome.org/GNOME/libxml2"
4BUGTRACKER = "http://bugzilla.gnome.org/buglist.cgi?product=libxml2" 4BUGTRACKER = "http://bugzilla.gnome.org/buglist.cgi?product=libxml2"
5SECTION = "libs" 5SECTION = "libs"
6LICENSE = "MIT" 6LICENSE = "MIT"
@@ -11,8 +11,9 @@ LIC_FILES_CHKSUM = "file://Copyright;md5=2044417e2e5006b65a8b9067b683fcf1 \
11 11
12DEPENDS = "zlib virtual/libiconv" 12DEPENDS = "zlib virtual/libiconv"
13 13
14SRC_URI = "http://www.xmlsoft.org/sources/libxml2-${PV}.tar.gz;name=libtar \ 14inherit gnomebase
15 http://www.w3.org/XML/Test/xmlts20080827.tar.gz;subdir=${BP};name=testtar \ 15
16SRC_URI += "http://www.w3.org/XML/Test/xmlts20080827.tar.gz;subdir=${BP};name=testtar \
16 file://libxml-64bit.patch \ 17 file://libxml-64bit.patch \
17 file://runtest.patch \ 18 file://runtest.patch \
18 file://run-ptest \ 19 file://run-ptest \
@@ -23,10 +24,31 @@ SRC_URI = "http://www.xmlsoft.org/sources/libxml2-${PV}.tar.gz;name=libtar \
23 file://CVE-2020-7595.patch \ 24 file://CVE-2020-7595.patch \
24 file://CVE-2019-20388.patch \ 25 file://CVE-2019-20388.patch \
25 file://CVE-2020-24977.patch \ 26 file://CVE-2020-24977.patch \
27 file://CVE-2021-3517.patch \
28 file://CVE-2021-3537.patch \
29 file://CVE-2021-3518.patch \
30 file://CVE-2021-3541.patch \
31 file://CVE-2022-23308.patch \
32 file://CVE-2022-23308-fix-regression.patch \
33 file://CVE-2022-29824-dependent.patch \
34 file://CVE-2022-29824.patch \
35 file://0001-Port-gentest.py-to-Python-3.patch \
36 file://CVE-2016-3709.patch \
37 file://CVE-2022-40303.patch \
38 file://CVE-2022-40304.patch \
39 file://CVE-2023-28484.patch \
40 file://CVE-2023-29469.patch \
41 file://CVE-2023-39615-pre.patch \
42 file://CVE-2023-39615-0001.patch \
43 file://CVE-2023-39615-0002.patch \
44 file://CVE-2021-3516.patch \
45 file://CVE-2023-45322-1.patch \
46 file://CVE-2023-45322-2.patch \
47 file://CVE-2024-25062-pre1.patch \
48 file://CVE-2024-25062.patch \
26 " 49 "
27 50
28SRC_URI[libtar.md5sum] = "10942a1dc23137a8aa07f0639cbfece5" 51SRC_URI[archive.sha256sum] = "593b7b751dd18c2d6abcd0c4bcb29efc203d0b4373a6df98e3a455ea74ae2813"
29SRC_URI[libtar.sha256sum] = "aafee193ffb8fe0c82d4afef6ef91972cbaf5feea100edc2f262750611b4be1f"
30SRC_URI[testtar.md5sum] = "ae3d1ebe000a3972afa104ca7f0e1b4a" 52SRC_URI[testtar.md5sum] = "ae3d1ebe000a3972afa104ca7f0e1b4a"
31SRC_URI[testtar.sha256sum] = "96151685cec997e1f9f3387e3626d61e6284d4d6e66e0e440c209286c03e9cc7" 53SRC_URI[testtar.sha256sum] = "96151685cec997e1f9f3387e3626d61e6284d4d6e66e0e440c209286c03e9cc7"
32 54
@@ -40,9 +62,9 @@ PACKAGECONFIG[ipv6] = "--enable-ipv6,--disable-ipv6,"
40 62
41inherit autotools pkgconfig binconfig-disabled ptest features_check 63inherit autotools pkgconfig binconfig-disabled ptest features_check
42 64
43inherit ${@bb.utils.contains('PACKAGECONFIG', 'python', 'python3native', '', d)} 65inherit ${@bb.utils.contains('PACKAGECONFIG', 'python', 'python3targetconfig', '', d)}
44 66
45RDEPENDS_${PN}-ptest += "make ${@bb.utils.contains('PACKAGECONFIG', 'python', 'libgcc python3-core python3-logging python3-shell python3-stringold python3-threading python3-unittest ${PN}-python', '', d)}" 67RDEPENDS_${PN}-ptest += "bash make ${@bb.utils.contains('PACKAGECONFIG', 'python', 'libgcc python3-core python3-logging python3-shell python3-stringold python3-threading python3-unittest ${PN}-python', '', d)}"
46 68
47RDEPENDS_${PN}-python += "${@bb.utils.contains('PACKAGECONFIG', 'python', 'python3-core', '', d)}" 69RDEPENDS_${PN}-python += "${@bb.utils.contains('PACKAGECONFIG', 'python', 'python3-core', '', d)}"
48 70
@@ -81,6 +103,16 @@ do_configure_prepend () {
81} 103}
82 104
83do_compile_ptest() { 105do_compile_ptest() {
106 # Make sure that testapi.c is newer than gentests.py, because
107 # with reproducible builds, they will both get e.g. Jan 1 1970
108 # modification time from SOURCE_DATE_EPOCH and then check-am
109 # might try to rebuild_testapi, which will fail even with
110 # 0001-Port-gentest.py-to-Python-3.patch, because it needs
111 # libxml2 module (libxml2-native dependency and correctly
112 # set PYTHON_SITE_PACKAGES), it's easier to
113 # just rely on pre-generated testapi.c from the release
114 touch ${S}/testapi.c
115
84 oe_runmake check-am 116 oe_runmake check-am
85} 117}
86 118
diff --git a/meta/recipes-core/meta/buildtools-tarball.bb b/meta/recipes-core/meta/buildtools-tarball.bb
index faf7108a86..24f5f28589 100644
--- a/meta/recipes-core/meta/buildtools-tarball.bb
+++ b/meta/recipes-core/meta/buildtools-tarball.bb
@@ -66,7 +66,7 @@ create_sdk_files_append () {
66 # Generate new (mini) sdk-environment-setup file 66 # Generate new (mini) sdk-environment-setup file
67 script=${1:-${SDK_OUTPUT}/${SDKPATH}/environment-setup-${SDK_SYS}} 67 script=${1:-${SDK_OUTPUT}/${SDKPATH}/environment-setup-${SDK_SYS}}
68 touch $script 68 touch $script
69 echo 'export PATH=${SDKPATHNATIVE}${bindir_nativesdk}:${SDKPATHNATIVE}${sbindir_nativesdk}:${SDKPATHNATIVE}${base_bindir_nativesdk}:${SDKPATHNATIVE}${base_sbindir_nativesdk}:$PATH' >> $script 69 echo 'export PATH="${SDKPATHNATIVE}${bindir_nativesdk}:${SDKPATHNATIVE}${sbindir_nativesdk}:${SDKPATHNATIVE}${base_bindir_nativesdk}:${SDKPATHNATIVE}${base_sbindir_nativesdk}:$PATH"' >> $script
70 echo 'export OECORE_NATIVE_SYSROOT="${SDKPATHNATIVE}"' >> $script 70 echo 'export OECORE_NATIVE_SYSROOT="${SDKPATHNATIVE}"' >> $script
71 echo 'export GIT_SSL_CAINFO="${SDKPATHNATIVE}${sysconfdir}/ssl/certs/ca-certificates.crt"' >>$script 71 echo 'export GIT_SSL_CAINFO="${SDKPATHNATIVE}${sysconfdir}/ssl/certs/ca-certificates.crt"' >>$script
72 echo 'export SSL_CERT_FILE="${SDKPATHNATIVE}${sysconfdir}/ssl/certs/ca-certificates.crt"' >>$script 72 echo 'export SSL_CERT_FILE="${SDKPATHNATIVE}${sysconfdir}/ssl/certs/ca-certificates.crt"' >>$script
diff --git a/meta/recipes-core/meta/cve-update-db-native.bb b/meta/recipes-core/meta/cve-update-db-native.bb
index 9e8e006a32..efc32470d3 100644
--- a/meta/recipes-core/meta/cve-update-db-native.bb
+++ b/meta/recipes-core/meta/cve-update-db-native.bb
@@ -12,28 +12,76 @@ deltask do_compile
12deltask do_install 12deltask do_install
13deltask do_populate_sysroot 13deltask do_populate_sysroot
14 14
15# CVE database update interval, in seconds. By default: once a day (24*60*60).
16# Use 0 to force the update
17# Use a negative value to skip the update
18CVE_DB_UPDATE_INTERVAL ?= "86400"
19
20# Timeout for blocking socket operations, such as the connection attempt.
21CVE_SOCKET_TIMEOUT ?= "60"
22NVDCVE_URL ?= "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-"
23
24CVE_DB_TEMP_FILE ?= "${CVE_CHECK_DB_DIR}/temp_nvdcve_1.1.db"
25
15python () { 26python () {
16 if not bb.data.inherits_class("cve-check", d): 27 if not bb.data.inherits_class("cve-check", d):
17 raise bb.parse.SkipRecipe("Skip recipe when cve-check class is not loaded.") 28 raise bb.parse.SkipRecipe("Skip recipe when cve-check class is not loaded.")
18} 29}
19 30
20python do_populate_cve_db() { 31python do_fetch() {
21 """ 32 """
22 Update NVD database with json data feed 33 Update NVD database with json data feed
23 """ 34 """
24 import bb.utils 35 import bb.utils
25 import bb.progress 36 import bb.progress
26 import sqlite3, urllib, urllib.parse, shutil, gzip 37 import shutil
27 from datetime import date
28 38
29 bb.utils.export_proxies(d) 39 bb.utils.export_proxies(d)
30 40
31 BASE_URL = "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-"
32 YEAR_START = 2002
33
34 db_file = d.getVar("CVE_CHECK_DB_FILE") 41 db_file = d.getVar("CVE_CHECK_DB_FILE")
35 db_dir = os.path.dirname(db_file) 42 db_dir = os.path.dirname(db_file)
43 db_tmp_file = d.getVar("CVE_DB_TEMP_FILE")
44
45 cleanup_db_download(db_file, db_tmp_file)
46
47 # The NVD database changes once a day, so no need to update more frequently
48 # Allow the user to force-update
49 try:
50 import time
51 update_interval = int(d.getVar("CVE_DB_UPDATE_INTERVAL"))
52 if update_interval < 0:
53 bb.note("CVE database update skipped")
54 return
55 if time.time() - os.path.getmtime(db_file) < update_interval:
56 return
36 57
58 except OSError:
59 pass
60
61 bb.utils.mkdirhier(db_dir)
62 if os.path.exists(db_file):
63 shutil.copy2(db_file, db_tmp_file)
64
65 if update_db_file(db_tmp_file, d) == True:
66 # Update downloaded correctly, can swap files
67 shutil.move(db_tmp_file, db_file)
68 else:
69 # Update failed, do not modify the database
70 bb.note("CVE database update failed")
71 os.remove(db_tmp_file)
72}
73
74do_fetch[lockfiles] += "${CVE_CHECK_DB_FILE_LOCK}"
75do_fetch[file-checksums] = ""
76do_fetch[vardeps] = ""
77
78def cleanup_db_download(db_file, db_tmp_file):
79 """
80 Cleanup the download space from possible failed downloads
81 """
82
83 # Clean up the updates done on the main file
84 # Remove it only if a journal file exists - it means a complete re-download
37 if os.path.exists("{0}-journal".format(db_file)): 85 if os.path.exists("{0}-journal".format(db_file)):
38 # If a journal is present the last update might have been interrupted. In that case, 86 # If a journal is present the last update might have been interrupted. In that case,
39 # just wipe any leftovers and force the DB to be recreated. 87 # just wipe any leftovers and force the DB to be recreated.
@@ -42,37 +90,50 @@ python do_populate_cve_db() {
42 if os.path.exists(db_file): 90 if os.path.exists(db_file):
43 os.remove(db_file) 91 os.remove(db_file)
44 92
45 # Don't refresh the database more than once an hour 93 # Clean-up the temporary file downloads, we can remove both journal
46 try: 94 # and the temporary database
47 import time 95 if os.path.exists("{0}-journal".format(db_tmp_file)):
48 if time.time() - os.path.getmtime(db_file) < (60*60): 96 # If a journal is present the last update might have been interrupted. In that case,
49 return 97 # just wipe any leftovers and force the DB to be recreated.
50 except OSError: 98 os.remove("{0}-journal".format(db_tmp_file))
51 pass
52 99
53 bb.utils.mkdirhier(db_dir) 100 if os.path.exists(db_tmp_file):
101 os.remove(db_tmp_file)
54 102
55 # Connect to database 103def update_db_file(db_tmp_file, d):
56 conn = sqlite3.connect(db_file) 104 """
57 c = conn.cursor() 105 Update the given database file
106 """
107 import bb.utils, bb.progress
108 from datetime import date
109 import urllib, gzip, sqlite3
58 110
59 initialize_db(c) 111 YEAR_START = 2002
112 cve_socket_timeout = int(d.getVar("CVE_SOCKET_TIMEOUT"))
113
114 # Connect to database
115 conn = sqlite3.connect(db_tmp_file)
116 initialize_db(conn)
60 117
61 with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f: 118 with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f:
62 total_years = date.today().year + 1 - YEAR_START 119 total_years = date.today().year + 1 - YEAR_START
63 for i, year in enumerate(range(YEAR_START, date.today().year + 1)): 120 for i, year in enumerate(range(YEAR_START, date.today().year + 1)):
121 bb.debug(2, "Updating %d" % year)
64 ph.update((float(i + 1) / total_years) * 100) 122 ph.update((float(i + 1) / total_years) * 100)
65 year_url = BASE_URL + str(year) 123 year_url = (d.getVar('NVDCVE_URL')) + str(year)
66 meta_url = year_url + ".meta" 124 meta_url = year_url + ".meta"
67 json_url = year_url + ".json.gz" 125 json_url = year_url + ".json.gz"
68 126
69 # Retrieve meta last modified date 127 # Retrieve meta last modified date
70 try: 128 try:
71 response = urllib.request.urlopen(meta_url) 129 response = urllib.request.urlopen(meta_url, timeout=cve_socket_timeout)
72 except urllib.error.URLError as e: 130 except urllib.error.URLError as e:
73 cve_f.write('Warning: CVE db update error, Unable to fetch CVE data.\n\n') 131 cve_f.write('Warning: CVE db update error, Unable to fetch CVE data.\n\n')
74 bb.warn("Failed to fetch CVE data (%s)" % e.reason) 132 bb.warn("Failed to fetch CVE data (%s)" % e)
75 return 133 import socket
134 result = socket.getaddrinfo("nvd.nist.gov", 443, proto=socket.IPPROTO_TCP)
135 bb.warn("Host IPs are %s" % (", ".join(t[4][0] for t in result)))
136 return False
76 137
77 if response: 138 if response:
78 for l in response.read().decode("utf-8").splitlines(): 139 for l in response.read().decode("utf-8").splitlines():
@@ -82,64 +143,81 @@ python do_populate_cve_db() {
82 break 143 break
83 else: 144 else:
84 bb.warn("Cannot parse CVE metadata, update failed") 145 bb.warn("Cannot parse CVE metadata, update failed")
85 return 146 return False
86 147
87 # Compare with current db last modified date 148 # Compare with current db last modified date
88 c.execute("select DATE from META where YEAR = ?", (year,)) 149 cursor = conn.execute("select DATE from META where YEAR = ?", (year,))
89 meta = c.fetchone() 150 meta = cursor.fetchone()
151 cursor.close()
152
90 if not meta or meta[0] != last_modified: 153 if not meta or meta[0] != last_modified:
154 bb.debug(2, "Updating entries")
91 # Clear products table entries corresponding to current year 155 # Clear products table entries corresponding to current year
92 c.execute("delete from PRODUCTS where ID like ?", ('CVE-%d%%' % year,)) 156 conn.execute("delete from PRODUCTS where ID like ?", ('CVE-%d%%' % year,)).close()
93 157
94 # Update db with current year json file 158 # Update db with current year json file
95 try: 159 try:
96 response = urllib.request.urlopen(json_url) 160 response = urllib.request.urlopen(json_url, timeout=cve_socket_timeout)
97 if response: 161 if response:
98 update_db(c, gzip.decompress(response.read()).decode('utf-8')) 162 update_db(conn, gzip.decompress(response.read()).decode('utf-8'))
99 c.execute("insert or replace into META values (?, ?)", [year, last_modified]) 163 conn.execute("insert or replace into META values (?, ?)", [year, last_modified]).close()
100 except urllib.error.URLError as e: 164 except urllib.error.URLError as e:
101 cve_f.write('Warning: CVE db update error, CVE data is outdated.\n\n') 165 cve_f.write('Warning: CVE db update error, CVE data is outdated.\n\n')
102 bb.warn("Cannot parse CVE data (%s), update failed" % e.reason) 166 bb.warn("Cannot parse CVE data (%s), update failed" % e.reason)
103 return 167 return False
104 168 else:
169 bb.debug(2, "Already up to date (last modified %s)" % last_modified)
105 # Update success, set the date to cve_check file. 170 # Update success, set the date to cve_check file.
106 if year == date.today().year: 171 if year == date.today().year:
107 cve_f.write('CVE database update : %s\n\n' % date.today()) 172 cve_f.write('CVE database update : %s\n\n' % date.today())
108 173
109 conn.commit() 174 conn.commit()
110 conn.close() 175 conn.close()
111} 176 return True
112 177
113do_populate_cve_db[lockfiles] += "${CVE_CHECK_DB_FILE_LOCK}" 178def initialize_db(conn):
179 with conn:
180 c = conn.cursor()
114 181
115def initialize_db(c): 182 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)")
116 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)")
117 183
118 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \ 184 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \
119 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)") 185 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)")
120 186
121 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \ 187 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \
122 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \ 188 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \
123 VERSION_END TEXT, OPERATOR_END TEXT)") 189 VERSION_END TEXT, OPERATOR_END TEXT)")
124 c.execute("CREATE INDEX IF NOT EXISTS PRODUCT_ID_IDX on PRODUCTS(ID);") 190 c.execute("CREATE INDEX IF NOT EXISTS PRODUCT_ID_IDX on PRODUCTS(ID);")
125 191
126def parse_node_and_insert(c, node, cveId): 192 c.close()
193
194def parse_node_and_insert(conn, node, cveId):
127 # Parse children node if needed 195 # Parse children node if needed
128 for child in node.get('children', ()): 196 for child in node.get('children', ()):
129 parse_node_and_insert(c, child, cveId) 197 parse_node_and_insert(conn, child, cveId)
130 198
131 def cpe_generator(): 199 def cpe_generator():
132 for cpe in node.get('cpe_match', ()): 200 for cpe in node.get('cpe_match', ()):
133 if not cpe['vulnerable']: 201 if not cpe['vulnerable']:
134 return 202 return
135 cpe23 = cpe['cpe23Uri'].split(':') 203 cpe23 = cpe.get('cpe23Uri')
204 if not cpe23:
205 return
206 cpe23 = cpe23.split(':')
207 if len(cpe23) < 6:
208 return
136 vendor = cpe23[3] 209 vendor = cpe23[3]
137 product = cpe23[4] 210 product = cpe23[4]
138 version = cpe23[5] 211 version = cpe23[5]
139 212
213 if cpe23[6] == '*' or cpe23[6] == '-':
214 version_suffix = ""
215 else:
216 version_suffix = "_" + cpe23[6]
217
140 if version != '*' and version != '-': 218 if version != '*' and version != '-':
141 # Version is defined, this is a '=' match 219 # Version is defined, this is a '=' match
142 yield [cveId, vendor, product, version, '=', '', ''] 220 yield [cveId, vendor, product, version + version_suffix, '=', '', '']
143 elif version == '-': 221 elif version == '-':
144 # no version information is available 222 # no version information is available
145 yield [cveId, vendor, product, version, '', '', ''] 223 yield [cveId, vendor, product, version, '', '', '']
@@ -173,9 +251,9 @@ def parse_node_and_insert(c, node, cveId):
173 # Save processing by representing as -. 251 # Save processing by representing as -.
174 yield [cveId, vendor, product, '-', '', '', ''] 252 yield [cveId, vendor, product, '-', '', '', '']
175 253
176 c.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator()) 254 conn.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator()).close()
177 255
178def update_db(c, jsondata): 256def update_db(conn, jsondata):
179 import json 257 import json
180 root = json.loads(jsondata) 258 root = json.loads(jsondata)
181 259
@@ -199,15 +277,14 @@ def update_db(c, jsondata):
199 accessVector = accessVector or "UNKNOWN" 277 accessVector = accessVector or "UNKNOWN"
200 cvssv3 = 0.0 278 cvssv3 = 0.0
201 279
202 c.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)", 280 conn.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)",
203 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]) 281 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]).close()
204 282
205 configurations = elt['configurations']['nodes'] 283 configurations = elt['configurations']['nodes']
206 for config in configurations: 284 for config in configurations:
207 parse_node_and_insert(c, config, cveId) 285 parse_node_and_insert(conn, config, cveId)
208 286
209 287
210addtask do_populate_cve_db before do_fetch 288do_fetch[nostamp] = "1"
211do_populate_cve_db[nostamp] = "1"
212 289
213EXCLUDE_FROM_WORLD = "1" 290EXCLUDE_FROM_WORLD = "1"
diff --git a/meta/recipes-core/meta/cve-update-nvd2-native.bb b/meta/recipes-core/meta/cve-update-nvd2-native.bb
new file mode 100644
index 0000000000..1a3eeba6d0
--- /dev/null
+++ b/meta/recipes-core/meta/cve-update-nvd2-native.bb
@@ -0,0 +1,372 @@
1SUMMARY = "Updates the NVD CVE database"
2LICENSE = "MIT"
3
4# Important note:
5# This product uses the NVD API but is not endorsed or certified by the NVD.
6
7INHIBIT_DEFAULT_DEPS = "1"
8
9inherit native
10
11deltask do_unpack
12deltask do_patch
13deltask do_configure
14deltask do_compile
15deltask do_install
16deltask do_populate_sysroot
17
18NVDCVE_URL ?= "https://services.nvd.nist.gov/rest/json/cves/2.0"
19
20# If you have a NVD API key (https://nvd.nist.gov/developers/request-an-api-key)
21# then setting this to get higher rate limits.
22NVDCVE_API_KEY ?= ""
23
24# CVE database update interval, in seconds. By default: once a day (24*60*60).
25# Use 0 to force the update
26# Use a negative value to skip the update
27CVE_DB_UPDATE_INTERVAL ?= "86400"
28
29# CVE database incremental update age threshold, in seconds. If the database is
30# older than this threshold, do a full re-download, else, do an incremental
31# update. By default: the maximum allowed value from NVD: 120 days (120*24*60*60)
32# Use 0 to force a full download.
33CVE_DB_INCR_UPDATE_AGE_THRES ?= "10368000"
34
35# Number of attempts for each http query to nvd server before giving up
36CVE_DB_UPDATE_ATTEMPTS ?= "5"
37
38CVE_DB_TEMP_FILE ?= "${CVE_CHECK_DB_DIR}/temp_nvdcve_2.db"
39
40python () {
41 if not bb.data.inherits_class("cve-check", d):
42 raise bb.parse.SkipRecipe("Skip recipe when cve-check class is not loaded.")
43}
44
45python do_fetch() {
46 """
47 Update NVD database with API 2.0
48 """
49 import bb.utils
50 import bb.progress
51 import shutil
52
53 bb.utils.export_proxies(d)
54
55 db_file = d.getVar("CVE_CHECK_DB_FILE")
56 db_dir = os.path.dirname(db_file)
57 db_tmp_file = d.getVar("CVE_DB_TEMP_FILE")
58
59 cleanup_db_download(db_file, db_tmp_file)
60 # By default let's update the whole database (since time 0)
61 database_time = 0
62
63 # The NVD database changes once a day, so no need to update more frequently
64 # Allow the user to force-update
65 try:
66 import time
67 update_interval = int(d.getVar("CVE_DB_UPDATE_INTERVAL"))
68 if update_interval < 0:
69 bb.note("CVE database update skipped")
70 return
71 if time.time() - os.path.getmtime(db_file) < update_interval:
72 bb.note("CVE database recently updated, skipping")
73 return
74 database_time = os.path.getmtime(db_file)
75
76 except OSError:
77 pass
78
79 bb.utils.mkdirhier(db_dir)
80 if os.path.exists(db_file):
81 shutil.copy2(db_file, db_tmp_file)
82
83 if update_db_file(db_tmp_file, d, database_time) == True:
84 # Update downloaded correctly, can swap files
85 shutil.move(db_tmp_file, db_file)
86 else:
87 # Update failed, do not modify the database
88 bb.warn("CVE database update failed")
89 os.remove(db_tmp_file)
90}
91
92do_fetch[lockfiles] += "${CVE_CHECK_DB_FILE_LOCK}"
93do_fetch[file-checksums] = ""
94do_fetch[vardeps] = ""
95
96def cleanup_db_download(db_file, db_tmp_file):
97 """
98 Cleanup the download space from possible failed downloads
99 """
100
101 # Clean up the updates done on the main file
102 # Remove it only if a journal file exists - it means a complete re-download
103 if os.path.exists("{0}-journal".format(db_file)):
104 # If a journal is present the last update might have been interrupted. In that case,
105 # just wipe any leftovers and force the DB to be recreated.
106 os.remove("{0}-journal".format(db_file))
107
108 if os.path.exists(db_file):
109 os.remove(db_file)
110
111 # Clean-up the temporary file downloads, we can remove both journal
112 # and the temporary database
113 if os.path.exists("{0}-journal".format(db_tmp_file)):
114 # If a journal is present the last update might have been interrupted. In that case,
115 # just wipe any leftovers and force the DB to be recreated.
116 os.remove("{0}-journal".format(db_tmp_file))
117
118 if os.path.exists(db_tmp_file):
119 os.remove(db_tmp_file)
120
121def nvd_request_wait(attempt, min_wait):
122 return min ( ( (2 * attempt) + min_wait ) , 30)
123
124def nvd_request_next(url, attempts, api_key, args, min_wait):
125 """
126 Request next part of the NVD database
127 NVD API documentation: https://nvd.nist.gov/developers/vulnerabilities
128 """
129
130 import urllib.request
131 import urllib.parse
132 import gzip
133 import http
134 import time
135
136 request = urllib.request.Request(url + "?" + urllib.parse.urlencode(args))
137 if api_key:
138 request.add_header("apiKey", api_key)
139 bb.note("Requesting %s" % request.full_url)
140
141 for attempt in range(attempts):
142 try:
143 r = urllib.request.urlopen(request)
144
145 if (r.headers['content-encoding'] == 'gzip'):
146 buf = r.read()
147 raw_data = gzip.decompress(buf).decode("utf-8")
148 else:
149 raw_data = r.read().decode("utf-8")
150
151 r.close()
152
153 except Exception as e:
154 wait_time = nvd_request_wait(attempt, min_wait)
155 bb.note("CVE database: received error (%s)" % (e))
156 bb.note("CVE database: retrying download after %d seconds. attempted (%d/%d)" % (wait_time, attempt+1, attempts))
157 time.sleep(wait_time)
158 pass
159 else:
160 return raw_data
161 else:
162 # We failed at all attempts
163 return None
164
165def update_db_file(db_tmp_file, d, database_time):
166 """
167 Update the given database file
168 """
169 import bb.utils, bb.progress
170 import datetime
171 import sqlite3
172 import json
173
174 # Connect to database
175 conn = sqlite3.connect(db_tmp_file)
176 initialize_db(conn)
177
178 req_args = {'startIndex' : 0}
179
180 incr_update_threshold = int(d.getVar("CVE_DB_INCR_UPDATE_AGE_THRES"))
181 if database_time != 0:
182 database_date = datetime.datetime.fromtimestamp(database_time, tz=datetime.timezone.utc)
183 today_date = datetime.datetime.now(tz=datetime.timezone.utc)
184 delta = today_date - database_date
185 if incr_update_threshold == 0:
186 bb.note("CVE database: forced full update")
187 elif delta < datetime.timedelta(seconds=incr_update_threshold):
188 bb.note("CVE database: performing partial update")
189 # The maximum range for time is 120 days
190 if delta > datetime.timedelta(days=120):
191 bb.error("CVE database: Trying to do an incremental update on a larger than supported range")
192 req_args['lastModStartDate'] = database_date.isoformat()
193 req_args['lastModEndDate'] = today_date.isoformat()
194 else:
195 bb.note("CVE database: file too old, forcing a full update")
196 else:
197 bb.note("CVE database: no preexisting database, do a full download")
198
199 with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f:
200
201 bb.note("Updating entries")
202 index = 0
203 url = d.getVar("NVDCVE_URL")
204 api_key = d.getVar("NVDCVE_API_KEY") or None
205 attempts = int(d.getVar("CVE_DB_UPDATE_ATTEMPTS"))
206
207 # Recommended by NVD
208 wait_time = 6
209 if api_key:
210 wait_time = 2
211
212 while True:
213 req_args['startIndex'] = index
214 raw_data = nvd_request_next(url, attempts, api_key, req_args, wait_time)
215 if raw_data is None:
216 # We haven't managed to download data
217 return False
218
219 data = json.loads(raw_data)
220
221 index = data["startIndex"]
222 total = data["totalResults"]
223 per_page = data["resultsPerPage"]
224 bb.note("Got %d entries" % per_page)
225 for cve in data["vulnerabilities"]:
226 update_db(conn, cve)
227
228 index += per_page
229 ph.update((float(index) / (total+1)) * 100)
230 if index >= total:
231 break
232
233 # Recommended by NVD
234 time.sleep(wait_time)
235
236 # Update success, set the date to cve_check file.
237 cve_f.write('CVE database update : %s\n\n' % datetime.date.today())
238
239 conn.commit()
240 conn.close()
241 return True
242
243def initialize_db(conn):
244 with conn:
245 c = conn.cursor()
246
247 c.execute("CREATE TABLE IF NOT EXISTS META (YEAR INTEGER UNIQUE, DATE TEXT)")
248
249 c.execute("CREATE TABLE IF NOT EXISTS NVD (ID TEXT UNIQUE, SUMMARY TEXT, \
250 SCOREV2 TEXT, SCOREV3 TEXT, MODIFIED INTEGER, VECTOR TEXT)")
251
252 c.execute("CREATE TABLE IF NOT EXISTS PRODUCTS (ID TEXT, \
253 VENDOR TEXT, PRODUCT TEXT, VERSION_START TEXT, OPERATOR_START TEXT, \
254 VERSION_END TEXT, OPERATOR_END TEXT)")
255 c.execute("CREATE INDEX IF NOT EXISTS PRODUCT_ID_IDX on PRODUCTS(ID);")
256
257 c.close()
258
259def parse_node_and_insert(conn, node, cveId):
260
261 def cpe_generator():
262 for cpe in node.get('cpeMatch', ()):
263 if not cpe['vulnerable']:
264 return
265 cpe23 = cpe.get('criteria')
266 if not cpe23:
267 return
268 cpe23 = cpe23.split(':')
269 if len(cpe23) < 6:
270 return
271 vendor = cpe23[3]
272 product = cpe23[4]
273 version = cpe23[5]
274
275 if cpe23[6] == '*' or cpe23[6] == '-':
276 version_suffix = ""
277 else:
278 version_suffix = "_" + cpe23[6]
279
280 if version != '*' and version != '-':
281 # Version is defined, this is a '=' match
282 yield [cveId, vendor, product, version + version_suffix, '=', '', '']
283 elif version == '-':
284 # no version information is available
285 yield [cveId, vendor, product, version, '', '', '']
286 else:
287 # Parse start version, end version and operators
288 op_start = ''
289 op_end = ''
290 v_start = ''
291 v_end = ''
292
293 if 'versionStartIncluding' in cpe:
294 op_start = '>='
295 v_start = cpe['versionStartIncluding']
296
297 if 'versionStartExcluding' in cpe:
298 op_start = '>'
299 v_start = cpe['versionStartExcluding']
300
301 if 'versionEndIncluding' in cpe:
302 op_end = '<='
303 v_end = cpe['versionEndIncluding']
304
305 if 'versionEndExcluding' in cpe:
306 op_end = '<'
307 v_end = cpe['versionEndExcluding']
308
309 if op_start or op_end or v_start or v_end:
310 yield [cveId, vendor, product, v_start, op_start, v_end, op_end]
311 else:
312 # This is no version information, expressed differently.
313 # Save processing by representing as -.
314 yield [cveId, vendor, product, '-', '', '', '']
315
316 conn.executemany("insert into PRODUCTS values (?, ?, ?, ?, ?, ?, ?)", cpe_generator()).close()
317
318def update_db(conn, elt):
319 """
320 Update a single entry in the on-disk database
321 """
322
323 accessVector = None
324 cveId = elt['cve']['id']
325 if elt['cve']['vulnStatus'] == "Rejected":
326 c = conn.cursor()
327 c.execute("delete from PRODUCTS where ID = ?;", [cveId])
328 c.execute("delete from NVD where ID = ?;", [cveId])
329 c.close()
330 return
331 cveDesc = ""
332 for desc in elt['cve']['descriptions']:
333 if desc['lang'] == 'en':
334 cveDesc = desc['value']
335 date = elt['cve']['lastModified']
336 try:
337 accessVector = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['accessVector']
338 cvssv2 = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['baseScore']
339 except KeyError:
340 cvssv2 = 0.0
341 cvssv3 = None
342 try:
343 accessVector = accessVector or elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['attackVector']
344 cvssv3 = elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['baseScore']
345 except KeyError:
346 pass
347 try:
348 accessVector = accessVector or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['attackVector']
349 cvssv3 = cvssv3 or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['baseScore']
350 except KeyError:
351 pass
352 accessVector = accessVector or "UNKNOWN"
353 cvssv3 = cvssv3 or 0.0
354
355 conn.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)",
356 [cveId, cveDesc, cvssv2, cvssv3, date, accessVector]).close()
357
358 try:
359 # Remove any pre-existing CVE configuration. Even for partial database
360 # update, those will be repopulated. This ensures that old
361 # configuration is not kept for an updated CVE.
362 conn.execute("delete from PRODUCTS where ID = ?", [cveId]).close()
363 for config in elt['cve']['configurations']:
364 # This is suboptimal as it doesn't handle AND/OR and negate, but is better than nothing
365 for node in config["nodes"]:
366 parse_node_and_insert(conn, node, cveId)
367 except KeyError:
368 bb.note("CVE %s has no configurations" % cveId)
369
370do_fetch[nostamp] = "1"
371
372EXCLUDE_FROM_WORLD = "1"
diff --git a/meta/recipes-core/musl/libucontext_git.bb b/meta/recipes-core/musl/libucontext_git.bb
index ec988f1920..71beb80083 100644
--- a/meta/recipes-core/musl/libucontext_git.bb
+++ b/meta/recipes-core/musl/libucontext_git.bb
@@ -10,7 +10,7 @@ DEPENDS = ""
10 10
11PV = "0.10+${SRCPV}" 11PV = "0.10+${SRCPV}"
12SRCREV = "19fa1bbfc26efb92147b5e85cc0ca02a0e837561" 12SRCREV = "19fa1bbfc26efb92147b5e85cc0ca02a0e837561"
13SRC_URI = "git://github.com/kaniini/libucontext \ 13SRC_URI = "git://github.com/kaniini/libucontext;branch=master;protocol=https \
14" 14"
15 15
16S = "${WORKDIR}/git" 16S = "${WORKDIR}/git"
diff --git a/meta/recipes-core/musl/musl-obstack.bb b/meta/recipes-core/musl/musl-obstack.bb
index 3003935fe5..74de48c2cd 100644
--- a/meta/recipes-core/musl/musl-obstack.bb
+++ b/meta/recipes-core/musl/musl-obstack.bb
@@ -10,7 +10,7 @@ SECTION = "libs"
10 10
11PV = "1.1" 11PV = "1.1"
12SRCREV = "d2ad66b0df44a4b784956f7f7f2717131ddc05f4" 12SRCREV = "d2ad66b0df44a4b784956f7f7f2717131ddc05f4"
13SRC_URI = "git://github.com/pullmoll/musl-obstack" 13SRC_URI = "git://github.com/pullmoll/musl-obstack;branch=master;protocol=https"
14 14
15UPSTREAM_CHECK_COMMITS = "1" 15UPSTREAM_CHECK_COMMITS = "1"
16 16
diff --git a/meta/recipes-core/musl/musl-utils.bb b/meta/recipes-core/musl/musl-utils.bb
index dd0ce33061..c30509469c 100644
--- a/meta/recipes-core/musl/musl-utils.bb
+++ b/meta/recipes-core/musl/musl-utils.bb
@@ -11,7 +11,7 @@ SECTION = "utils"
11PV = "20170421" 11PV = "20170421"
12 12
13SRCREV = "fb5630138ccabbbc14a19d372096a04e42573c7d" 13SRCREV = "fb5630138ccabbbc14a19d372096a04e42573c7d"
14SRC_URI = "git://github.com/boltlinux/musl-utils" 14SRC_URI = "git://github.com/boltlinux/musl-utils;branch=master;protocol=https"
15 15
16UPSTREAM_CHECK_COMMITS = "1" 16UPSTREAM_CHECK_COMMITS = "1"
17 17
diff --git a/meta/recipes-core/musl/musl_git.bb b/meta/recipes-core/musl/musl_git.bb
index 82379fd1c5..cbb56f4769 100644
--- a/meta/recipes-core/musl/musl_git.bb
+++ b/meta/recipes-core/musl/musl_git.bb
@@ -12,7 +12,7 @@ PV = "${BASEVER}+git${SRCPV}"
12 12
13# mirror is at git://github.com/kraj/musl.git 13# mirror is at git://github.com/kraj/musl.git
14 14
15SRC_URI = "git://git.musl-libc.org/musl \ 15SRC_URI = "git://git.musl-libc.org/musl;branch=master \
16 file://0001-Make-dynamic-linker-a-relative-symlink-to-libc.patch \ 16 file://0001-Make-dynamic-linker-a-relative-symlink-to-libc.patch \
17 file://0002-ldso-Use-syslibdir-and-libdir-as-default-pathes-to-l.patch \ 17 file://0002-ldso-Use-syslibdir-and-libdir-as-default-pathes-to-l.patch \
18 " 18 "
diff --git a/meta/recipes-core/ncurses/files/CVE-2021-39537.patch b/meta/recipes-core/ncurses/files/CVE-2021-39537.patch
new file mode 100644
index 0000000000..7655200350
--- /dev/null
+++ b/meta/recipes-core/ncurses/files/CVE-2021-39537.patch
@@ -0,0 +1,30 @@
1$NetBSD: patch-ncurses_tinfo_captoinfo.c,v 1.1 2021/10/09 07:52:36 wiz Exp $
2
3Fix for CVE-2021-39537 from upstream:
4https://github.com/ThomasDickey/ncurses-snapshots/commit/63ca9e061f4644795d6f3f559557f3e1ed8c738b#diff-7e95c7bc5f213e9be438e69a9d5d0f261a14952bcbd692f7b9014217b8047340
5
6CVE: CVE-2021-39537
7Upstream-Status: Backport [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]
8Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
9
10--- a/ncurses/tinfo/captoinfo.c 2020-02-02 23:34:34.000000000 +0000
11+++ b/ncurses/tinfo/captoinfo.c
12@@ -216,12 +216,15 @@ cvtchar(register const char *sp)
13 }
14 break;
15 case '^':
16+ len = 2;
17 c = UChar(*++sp);
18- if (c == '?')
19+ if (c == '?') {
20 c = 127;
21- else
22+ } else if (c == '\0') {
23+ len = 1;
24+ } else {
25 c &= 0x1f;
26- len = 2;
27+ }
28 break;
29 default:
30 c = UChar(*sp);
diff --git a/meta/recipes-core/ncurses/files/CVE-2022-29458.patch b/meta/recipes-core/ncurses/files/CVE-2022-29458.patch
new file mode 100644
index 0000000000..eb1b7c96f9
--- /dev/null
+++ b/meta/recipes-core/ncurses/files/CVE-2022-29458.patch
@@ -0,0 +1,135 @@
1From 5f40697e37e195069f55528fc7a1d77e619ad104 Mon Sep 17 00:00:00 2001
2From: Dan Tran <dantran@microsoft.com>
3Date: Fri, 13 May 2022 13:28:41 -0700
4Subject: [PATCH] ncurses 6.3 before patch 20220416 has an out-of-bounds read
5 and segmentation violation in convert_strings in tinfo/read_entry.c in the
6 terminfo library.
7
8CVE: CVE-2022-29458
9Upstream-Status: Backport
10[https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1009870]
11
12Signed-off-by: Gustavo Lima Chaves <gustavo.chaves@microsoft.com>
13Signed-off-by: Dan Tran <dantran@microsoft.com>
14---
15 ncurses/tinfo/alloc_entry.c | 14 ++++++--------
16 ncurses/tinfo/read_entry.c | 25 +++++++++++++++++++------
17 2 files changed, 25 insertions(+), 14 deletions(-)
18
19diff --git a/ncurses/tinfo/alloc_entry.c b/ncurses/tinfo/alloc_entry.c
20index 4bf7d6c8..b49ad6aa 100644
21--- a/ncurses/tinfo/alloc_entry.c
22+++ b/ncurses/tinfo/alloc_entry.c
23@@ -48,13 +48,11 @@
24
25 #include <tic.h>
26
27-MODULE_ID("$Id: alloc_entry.c,v 1.64 2020/02/02 23:34:34 tom Exp $")
28+MODULE_ID("$Id: alloc_entry.c,v 1.69 2022/04/16 22:46:53 tom Exp $")
29
30 #define ABSENT_OFFSET -1
31 #define CANCELLED_OFFSET -2
32
33-#define MAX_STRTAB 4096 /* documented maximum entry size */
34-
35 static char *stringbuf; /* buffer for string capabilities */
36 static size_t next_free; /* next free character in stringbuf */
37
38@@ -71,8 +69,8 @@ _nc_init_entry(ENTRY * const tp)
39 }
40 #endif
41
42- if (stringbuf == 0)
43- TYPE_MALLOC(char, (size_t) MAX_STRTAB, stringbuf);
44+ if (stringbuf == NULL)
45+ TYPE_MALLOC(char, (size_t) MAX_ENTRY_SIZE, stringbuf);
46
47 next_free = 0;
48
49@@ -108,11 +106,11 @@ _nc_save_str(const char *const string)
50 * Cheat a little by making an empty string point to the end of the
51 * previous string.
52 */
53- if (next_free < MAX_STRTAB) {
54+ if (next_free < MAX_ENTRY_SIZE) {
55 result = (stringbuf + next_free - 1);
56 }
57- } else if (next_free + len < MAX_STRTAB) {
58- _nc_STRCPY(&stringbuf[next_free], string, MAX_STRTAB);
59+ } else if (next_free + len < MAX_ENTRY_SIZE) {
60+ _nc_STRCPY(&stringbuf[next_free], string, MAX_ENTRY_SIZE);
61 DEBUG(7, ("Saved string %s", _nc_visbuf(string)));
62 DEBUG(7, ("at location %d", (int) next_free));
63 next_free += len;
64diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c
65index 5b570b0f..23c2cebc 100644
66--- a/ncurses/tinfo/read_entry.c
67+++ b/ncurses/tinfo/read_entry.c
68@@ -1,5 +1,5 @@
69 /****************************************************************************
70- * Copyright 2018-2019,2020 Thomas E. Dickey *
71+ * Copyright 2018-2021,2022 Thomas E. Dickey *
72 * Copyright 1998-2016,2017 Free Software Foundation, Inc. *
73 * *
74 * Permission is hereby granted, free of charge, to any person obtaining a *
75@@ -42,7 +42,7 @@
76
77 #include <tic.h>
78
79-MODULE_ID("$Id: read_entry.c,v 1.157 2020/02/02 23:34:34 tom Exp $")
80+MODULE_ID("$Id: read_entry.c,v 1.162 2022/04/16 21:00:00 tom Exp $")
81
82 #define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
83
84@@ -145,6 +145,7 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table)
85 {
86 int i;
87 char *p;
88+ bool corrupt = FALSE;
89
90 for (i = 0; i < count; i++) {
91 if (IS_NEG1(buf + 2 * i)) {
92@@ -154,8 +155,20 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table)
93 } else if (MyNumber(buf + 2 * i) > size) {
94 Strings[i] = ABSENT_STRING;
95 } else {
96- Strings[i] = (MyNumber(buf + 2 * i) + table);
97- TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i])));
98+ int nn = MyNumber(buf + 2 * i);
99+ if (nn >= 0 && nn < size) {
100+ Strings[i] = (nn + table);
101+ TR(TRACE_DATABASE, ("Strings[%d] = %s", i,
102+ _nc_visbuf(Strings[i])));
103+ } else {
104+ if (!corrupt) {
105+ corrupt = TRUE;
106+ TR(TRACE_DATABASE,
107+ ("ignore out-of-range index %d to Strings[]", nn));
108+ _nc_warning("corrupt data found in convert_strings");
109+ }
110+ Strings[i] = ABSENT_STRING;
111+ }
112 }
113
114 /* make sure all strings are NUL terminated */
115@@ -776,7 +789,7 @@ _nc_read_tic_entry(char *filename,
116 * looking for compiled (binary) terminfo data.
117 *
118 * cgetent uses a two-level lookup. On the first it uses the given
119- * name to return a record containing only the aliases for an entry.
120+ * name to return a record containing only the aliases for an entry.
121 * On the second (using that list of aliases as a key), it returns the
122 * content of the terminal description. We expect second lookup to
123 * return data beginning with the same set of aliases.
124@@ -833,7 +846,7 @@ _nc_read_tic_entry(char *filename,
125 #endif /* NCURSES_USE_DATABASE */
126
127 /*
128- * Find and read the compiled entry for a given terminal type, if it exists.
129+ * Find and read the compiled entry for a given terminal type, if it exists.
130 * We take pains here to make sure no combination of environment variables and
131 * terminal type name can be used to overrun the file buffer.
132 */
133--
1342.36.1
135
diff --git a/meta/recipes-core/ncurses/files/CVE-2023-29491.patch b/meta/recipes-core/ncurses/files/CVE-2023-29491.patch
new file mode 100644
index 0000000000..0a0497723f
--- /dev/null
+++ b/meta/recipes-core/ncurses/files/CVE-2023-29491.patch
@@ -0,0 +1,45 @@
1Backport of:
2
3Author: Sven Joachim <svenjoac@gmx.de>
4Description: Change the --disable-root-environ configure option behavior
5 By default, the --disable-root-environ option forbids program run by
6 the superuser to load custom terminfo entries. This patch changes
7 that to only restrict programs running with elevated privileges,
8 matching the behavior of the --disable-setuid-environ option
9 introduced in the 20230423 upstream patchlevel.
10Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1034372#29
11Bug: https://lists.gnu.org/archive/html/bug-ncurses/2023-04/msg00018.html
12Forwarded: not-needed
13Last-Update: 2023-05-01
14
15Upstream-Status: Backport [https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/ncurses/6.2-0ubuntu2.1/ncurses_6.2-0ubuntu2.1.debian.tar.xz]
16CVE: CVE-2023-29491
17Signed-off-by: Virendra Thakur <virendrak@kpit.com>
18
19---
20 ncurses/tinfo/access.c | 2 --
21 1 file changed, 2 deletions(-)
22
23--- a/ncurses/tinfo/access.c
24+++ b/ncurses/tinfo/access.c
25@@ -178,15 +178,16 @@ _nc_is_file_path(const char *path)
26 NCURSES_EXPORT(int)
27 _nc_env_access(void)
28 {
29+ int result = TRUE;
30+
31 #if HAVE_ISSETUGID
32 if (issetugid())
33- return FALSE;
34+ result = FALSE;
35 #elif HAVE_GETEUID && HAVE_GETEGID
36 if (getuid() != geteuid()
37 || getgid() != getegid())
38- return FALSE;
39+ result = FALSE;
40 #endif
41- /* ...finally, disallow root */
42- return (getuid() != ROOT_UID) && (geteuid() != ROOT_UID);
43+ return result;
44 }
45 #endif
diff --git a/meta/recipes-core/ncurses/files/CVE-2023-50495.patch b/meta/recipes-core/ncurses/files/CVE-2023-50495.patch
new file mode 100644
index 0000000000..58c23866d1
--- /dev/null
+++ b/meta/recipes-core/ncurses/files/CVE-2023-50495.patch
@@ -0,0 +1,79 @@
1Fix for CVE-2023-50495 from upstream:
2https://github.com/ThomasDickey/ncurses-snapshots/commit/efe9674ee14b14b788f9618941f97d31742f0adc
3
4Reference:
5https://invisible-island.net/archives/ncurses/6.4/ncurses-6.4-20230424.patch.gz
6
7Upstream-Status: Backport [import from suse ftp.pbone.net/mirror/ftp.opensuse.org/update/leap-micro/5.3/sle/src/ncurses-6.1-150000.5.20.1.src.rpm
8Upstream commit https://github.com/ThomasDickey/ncurses-snapshots/commit/efe9674ee14b14b788f9618941f97d31742f0adc]
9CVE: CVE-2023-50495
10Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
11---
12 ncurses/tinfo/parse_entry.c | 23 ++++++++++++++++-------
13 1 file changed, 16 insertions(+), 7 deletions(-)
14
15diff --git a/ncurses/tinfo/parse_entry.c b/ncurses/tinfo/parse_entry.c
16index 23574b66..56ba9ae6 100644
17--- a/ncurses/tinfo/parse_entry.c
18+++ b/ncurses/tinfo/parse_entry.c
19@@ -110,7 +110,7 @@ _nc_extend_names(ENTRY * entryp, const char *name, int token_type)
20 /* Well, we are given a cancel for a name that we don't recognize */
21 return _nc_extend_names(entryp, name, STRING);
22 default:
23- return 0;
24+ return NULL;
25 }
26
27 /* Adjust the 'offset' (insertion-point) to keep the lists of extended
28@@ -142,6 +142,11 @@ _nc_extend_names(ENTRY * entryp, const char *name, int token_type)
29 for (last = (unsigned) (max - 1); last > tindex; last--)
30
31 if (!found) {
32+ char *saved;
33+
34+ if ((saved = _nc_save_str(name)) == NULL)
35+ return NULL;
36+
37 switch (token_type) {
38 case BOOLEAN:
39 tp->ext_Booleans++;
40@@ -169,7 +174,7 @@ _nc_extend_names(ENTRY * entryp, const char *name, int token_type)
41 TYPE_REALLOC(char *, actual, tp->ext_Names);
42 while (--actual > offset)
43 tp->ext_Names[actual] = tp->ext_Names[actual - 1];
44- tp->ext_Names[offset] = _nc_save_str(name);
45+ tp->ext_Names[offset] = saved;
46 }
47
48 temp.nte_name = tp->ext_Names[offset];
49@@ -337,6 +342,8 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent)
50 bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0);
51 bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0);
52 if (is_use || is_tc) {
53+ char *saved;
54+
55 if (!VALID_STRING(_nc_curr_token.tk_valstring)
56 || _nc_curr_token.tk_valstring[0] == '\0') {
57 _nc_warning("missing name for use-clause");
58@@ -350,11 +357,13 @@ _nc_parse_entry(ENTRY * entryp, int literal, bool silent)
59 _nc_curr_token.tk_valstring);
60 continue;
61 }
62- entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring);
63- entryp->uses[entryp->nuses].line = _nc_curr_line;
64- entryp->nuses++;
65- if (entryp->nuses > 1 && is_tc) {
66- BAD_TC_USAGE
67+ if ((saved = _nc_save_str(_nc_curr_token.tk_valstring)) != NULL) {
68+ entryp->uses[entryp->nuses].name = saved;
69+ entryp->uses[entryp->nuses].line = _nc_curr_line;
70+ entryp->nuses++;
71+ if (entryp->nuses > 1 && is_tc) {
72+ BAD_TC_USAGE
73+ }
74 }
75 } else {
76 /* normal token lookup */
77--
782.25.1
79
diff --git a/meta/recipes-core/ncurses/ncurses.inc b/meta/recipes-core/ncurses/ncurses.inc
index 7f1834f0dc..ee0b15ecf0 100644
--- a/meta/recipes-core/ncurses/ncurses.inc
+++ b/meta/recipes-core/ncurses/ncurses.inc
@@ -13,7 +13,7 @@ BINCONFIG = "${bindir}/ncurses5-config ${bindir}/ncursesw5-config \
13inherit autotools binconfig-disabled multilib_header pkgconfig 13inherit autotools binconfig-disabled multilib_header pkgconfig
14 14
15# Upstream has useful patches at times at ftp://invisible-island.net/ncurses/ 15# Upstream has useful patches at times at ftp://invisible-island.net/ncurses/
16SRC_URI = "git://salsa.debian.org/debian/ncurses.git;protocol=https" 16SRC_URI = "git://salsa.debian.org/debian/ncurses.git;protocol=https;branch=master"
17 17
18EXTRA_AUTORECONF = "-I m4" 18EXTRA_AUTORECONF = "-I m4"
19 19
diff --git a/meta/recipes-core/ncurses/ncurses_6.2.bb b/meta/recipes-core/ncurses/ncurses_6.2.bb
index 76f0cf97f4..dbff149f55 100644
--- a/meta/recipes-core/ncurses/ncurses_6.2.bb
+++ b/meta/recipes-core/ncurses/ncurses_6.2.bb
@@ -3,11 +3,15 @@ require ncurses.inc
3SRC_URI += "file://0001-tic-hang.patch \ 3SRC_URI += "file://0001-tic-hang.patch \
4 file://0002-configure-reproducible.patch \ 4 file://0002-configure-reproducible.patch \
5 file://0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch \ 5 file://0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch \
6 file://CVE-2021-39537.patch \
7 file://CVE-2022-29458.patch \
8 file://CVE-2023-29491.patch \
9 file://CVE-2023-50495.patch \
6 " 10 "
7# commit id corresponds to the revision in package version 11# commit id corresponds to the revision in package version
8SRCREV = "a669013cd5e9d6434e5301348ea51baf306c93c4" 12SRCREV = "a669013cd5e9d6434e5301348ea51baf306c93c4"
9S = "${WORKDIR}/git" 13S = "${WORKDIR}/git"
10EXTRA_OECONF += "--with-abi-version=5" 14EXTRA_OECONF += "--with-abi-version=5 --disable-root-environ"
11UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+(\.\d+)+(\+\d+)*)" 15UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+(\.\d+)+(\+\d+)*)"
12 16
13# This is needed when using patchlevel versions like 6.1+20181013 17# This is needed when using patchlevel versions like 6.1+20181013
diff --git a/meta/recipes-core/os-release/os-release.bb b/meta/recipes-core/os-release/os-release.bb
index a29d678125..33f75e39b8 100644
--- a/meta/recipes-core/os-release/os-release.bb
+++ b/meta/recipes-core/os-release/os-release.bb
@@ -12,7 +12,9 @@ do_configure[noexec] = "1"
12 12
13# Other valid fields: BUILD_ID ID_LIKE ANSI_COLOR CPE_NAME 13# Other valid fields: BUILD_ID ID_LIKE ANSI_COLOR CPE_NAME
14# HOME_URL SUPPORT_URL BUG_REPORT_URL 14# HOME_URL SUPPORT_URL BUG_REPORT_URL
15OS_RELEASE_FIELDS = "ID ID_LIKE NAME VERSION VERSION_ID PRETTY_NAME" 15OS_RELEASE_FIELDS = "\
16 ID ID_LIKE NAME VERSION VERSION_ID PRETTY_NAME DISTRO_CODENAME \
17"
16OS_RELEASE_UNQUOTED_FIELDS = "ID VERSION_ID VARIANT_ID" 18OS_RELEASE_UNQUOTED_FIELDS = "ID VERSION_ID VARIANT_ID"
17 19
18ID = "${DISTRO}" 20ID = "${DISTRO}"
diff --git a/meta/recipes-core/ovmf/ovmf/0001-Basetools-genffs-fix-gcc12-warning.patch b/meta/recipes-core/ovmf/ovmf/0001-Basetools-genffs-fix-gcc12-warning.patch
new file mode 100644
index 0000000000..4418d52898
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-Basetools-genffs-fix-gcc12-warning.patch
@@ -0,0 +1,49 @@
1From 7b005f344e533cd913c3ca05b266f9872df886d1 Mon Sep 17 00:00:00 2001
2From: Gerd Hoffmann <kraxel@redhat.com>
3Date: Thu, 24 Mar 2022 20:04:34 +0800
4Subject: [PATCH] BaseTools: fix gcc12 warning
5
6GenFfs.c:545:5: error: pointer ?InFileHandle? used after ?fclose? [-Werror=use-after-free]
7 545 | Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);
8 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9GenFfs.c:544:5: note: call to ?fclose? here
10 544 | fclose (InFileHandle);
11 | ^~~~~~~~~~~~~~~~~~~~~
12
13Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
14Reviewed-by: Bob Feng <bob.c.feng@intel.com>
15
16Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/7b005f344e533cd913c3ca05b266f9872df886d1]
17Signed-off-by: Steve Sakoman <steve@sakoman.com>
18
19---
20 BaseTools/Source/C/GenFfs/GenFfs.c | 2 +-
21 BaseTools/Source/C/GenSec/GenSec.c | 2 +-
22 2 files changed, 2 insertions(+), 2 deletions(-)
23
24diff --git a/BaseTools/Source/C/GenFfs/GenFfs.c b/BaseTools/Source/C/GenFfs/GenFfs.c
25index 949025c33325..d78d62ab3689 100644
26--- a/BaseTools/Source/C/GenFfs/GenFfs.c
27+++ b/BaseTools/Source/C/GenFfs/GenFfs.c
28@@ -542,7 +542,7 @@ GetAlignmentFromFile(char *InFile, UINT32 *Alignment)
29 PeFileBuffer = (UINT8 *) malloc (PeFileSize);
30 if (PeFileBuffer == NULL) {
31 fclose (InFileHandle);
32- Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);
33+ Error(NULL, 0, 4001, "Resource", "memory cannot be allocated for %s", InFile);
34 return EFI_OUT_OF_RESOURCES;
35 }
36 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);
37diff --git a/BaseTools/Source/C/GenSec/GenSec.c b/BaseTools/Source/C/GenSec/GenSec.c
38index d54a4f9e0a7d..b1d05367ec0b 100644
39--- a/BaseTools/Source/C/GenSec/GenSec.c
40+++ b/BaseTools/Source/C/GenSec/GenSec.c
41@@ -1062,7 +1062,7 @@ GetAlignmentFromFile(char *InFile, UINT32 *Alignment)
42 PeFileBuffer = (UINT8 *) malloc (PeFileSize);
43 if (PeFileBuffer == NULL) {
44 fclose (InFileHandle);
45- Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);
46+ Error(NULL, 0, 4001, "Resource", "memory cannot be allocated for %s", InFile);
47 return EFI_OUT_OF_RESOURCES;
48 }
49 fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);
diff --git a/meta/recipes-core/ovmf/ovmf/0001-Basetools-lzmaenc-fix-gcc12-warning.patch b/meta/recipes-core/ovmf/ovmf/0001-Basetools-lzmaenc-fix-gcc12-warning.patch
new file mode 100644
index 0000000000..a6ef87aa79
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-Basetools-lzmaenc-fix-gcc12-warning.patch
@@ -0,0 +1,53 @@
1From 24551a99d1f765c891a4dc21a36f18ccbf56e612 Mon Sep 17 00:00:00 2001
2From: Steve Sakoman <steve@sakoman.com>
3Date: Tue, 10 Jan 2023 06:15:00 -1000
4Subject: [PATCH] BaseTools: fix gcc12 warning
5
6Sdk/C/LzmaEnc.c: In function ?LzmaEnc_CodeOneMemBlock?:
7Sdk/C/LzmaEnc.c:2828:19: error: storing the address of local variable ?outStream? in ?*p.rc.outStream? [-Werror=dangling-pointer=]
8 2828 | p->rc.outStream = &outStream.vt;
9 | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
10Sdk/C/LzmaEnc.c:2811:28: note: ?outStream? declared here
11 2811 | CLzmaEnc_SeqOutStreamBuf outStream;
12 | ^~~~~~~~~
13Sdk/C/LzmaEnc.c:2811:28: note: ?pp? declared here
14Sdk/C/LzmaEnc.c:2828:19: error: storing the address of local variable ?outStream? in ?*(CLzmaEnc *)pp.rc.outStream? [-Werror=dangling-pointer=]
15 2828 | p->rc.outStream = &outStream.vt;
16 | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
17Sdk/C/LzmaEnc.c:2811:28: note: ?outStream? declared here
18 2811 | CLzmaEnc_SeqOutStreamBuf outStream;
19 | ^~~~~~~~~
20Sdk/C/LzmaEnc.c:2811:28: note: ?pp? declared here
21cc1: all warnings being treated as errors
22
23Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
24Reviewed-by: Bob Feng <bob.c.feng@intel.com>
25
26Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/85021f8cf22d1bd4114803c6c610dea5ef0059f1]
27Signed-off-by: Steve Sakoman <steve@sakoman.com>
28---
29 BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c | 3 ++-
30 1 file changed, 2 insertions(+), 1 deletion(-)
31
32diff --git a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
33index e281716fee..b575c4f888 100644
34--- a/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
35+++ b/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
36@@ -2638,12 +2638,13 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
37
38 nowPos64 = p->nowPos64;
39 RangeEnc_Init(&p->rc);
40- p->rc.outStream = &outStream.vt;
41
42 if (desiredPackSize == 0)
43 return SZ_ERROR_OUTPUT_EOF;
44
45+ p->rc.outStream = &outStream.vt;
46 res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
47+ p->rc.outStream = NULL;
48
49 *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
50 *destLen -= outStream.rem;
51--
522.25.1
53
diff --git a/meta/recipes-core/ovmf/ovmf/0001-Basetools-turn-off-gcc12-warning.patch b/meta/recipes-core/ovmf/ovmf/0001-Basetools-turn-off-gcc12-warning.patch
new file mode 100644
index 0000000000..73a432684c
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-Basetools-turn-off-gcc12-warning.patch
@@ -0,0 +1,41 @@
1From 22130dcd98b4d4b76ac8d922adb4a2dbc86fa52c Mon Sep 17 00:00:00 2001
2From: Gerd Hoffmann <kraxel@redhat.com>
3Date: Thu, 24 Mar 2022 20:04:36 +0800
4Subject: [PATCH] Basetools: turn off gcc12 warning
5
6In function ?SetDevicePathEndNode?,
7 inlined from ?FileDevicePath? at DevicePathUtilities.c:857:5:
8DevicePathUtilities.c:321:3: error: writing 4 bytes into a region of size 1 [-Werror=stringop-overflow=]
9 321 | memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath));
10 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11In file included from UefiDevicePathLib.h:22,
12 from DevicePathUtilities.c:16:
13../Include/Protocol/DevicePath.h: In function ?FileDevicePath?:
14../Include/Protocol/DevicePath.h:51:9: note: destination object ?Type? of size 1
15 51 | UINT8 Type; ///< 0x01 Hardware Device Path.
16 | ^~~~
17
18Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
19Reviewed-by: Bob Feng <bob.c.feng@intel.com>
20
21Upstream-Status: Backport [https://github.com/tianocore/edk2/commit/22130dcd98b4d4b76ac8d922adb4a2dbc86fa52c]
22Signed-off-by: Steve Sakoman <steve@sakoman.com>
23
24---
25 BaseTools/Source/C/DevicePath/GNUmakefile | 3 +++
26 1 file changed, 3 insertions(+)
27
28diff --git a/BaseTools/Source/C/DevicePath/GNUmakefile b/BaseTools/Source/C/DevicePath/GNUmakefile
29index 7ca08af9662d..b05d2bddfa68 100644
30--- a/BaseTools/Source/C/DevicePath/GNUmakefile
31+++ b/BaseTools/Source/C/DevicePath/GNUmakefile
32@@ -13,6 +13,9 @@ OBJECTS = DevicePath.o UefiDevicePathLib.o DevicePathFromText.o DevicePathUtili
33
34 include $(MAKEROOT)/Makefiles/app.makefile
35
36+# gcc 12 trips over device path handling
37+BUILD_CFLAGS += -Wno-error=stringop-overflow
38+
39 LIBS = -lCommon
40 ifeq ($(CYGWIN), CYGWIN)
41 LIBS += -L/lib/e2fsprogs -luuid
diff --git a/meta/recipes-core/ovmf/ovmf/0001-Fix-VLA-parameter-warning.patch b/meta/recipes-core/ovmf/ovmf/0001-Fix-VLA-parameter-warning.patch
new file mode 100644
index 0000000000..d658123b81
--- /dev/null
+++ b/meta/recipes-core/ovmf/ovmf/0001-Fix-VLA-parameter-warning.patch
@@ -0,0 +1,51 @@
1From 498627ebda6271b59920f43a0b9b6187edeb7b09 Mon Sep 17 00:00:00 2001
2From: Adrian Herrera <adr.her.arc.95@gmail.com>
3Date: Mon, 22 Mar 2021 21:06:47 +0000
4Subject: [PATCH] Fix VLA parameter warning
5
6Make VLA buffer types consistent in declarations and definitions.
7Resolves build crash when using -Werror due to "vla-parameter" warning.
8
9Upstream-Status: Submitted [https://github.com/google/brotli/pull/893]
10Signed-off-by: Adrian Herrera <adr.her.arc.95@gmail.com>
11---
12 c/dec/decode.c | 6 ++++--
13 c/enc/encode.c | 5 +++--
14 2 files changed, 7 insertions(+), 4 deletions(-)
15
16diff --git a/BaseTools/Source/C/BrotliCompress/brotli/c/dec/decode.c b/BaseTools/Source/C/BrotliCompress/brotli/c/dec/decode.c
17index 114c505..bb6f1ab 100644
18--- a/BaseTools/Source/C/BrotliCompress/brotli/c/dec/decode.c
19+++ b/BaseTools/Source/C/BrotliCompress/brotli/c/dec/decode.c
20@@ -2030,8 +2030,10 @@ static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
21 }
22
23 BrotliDecoderResult BrotliDecoderDecompress(
24- size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size,
25- uint8_t* decoded_buffer) {
26+ size_t encoded_size,
27+ const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
28+ size_t* decoded_size,
29+ uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]) {
30 BrotliDecoderState s;
31 BrotliDecoderResult result;
32 size_t total_out = 0;
33diff --git a/c/enc/encode.c b/c/enc/encode.c
34index 68548ef..ab0a490 100644
35--- a/BaseTools/Source/C/BrotliCompress/brotli/c/enc/encode.c
36+++ c/BaseTools/Source/C/BrotliCompress/brotli/c/enc/encode.c
37@@ -1470,8 +1470,9 @@ static size_t MakeUncompressedStream(
38
39 BROTLI_BOOL BrotliEncoderCompress(
40 int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
41- const uint8_t* input_buffer, size_t* encoded_size,
42- uint8_t* encoded_buffer) {
43+ const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],
44+ size_t* encoded_size,
45+ uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) {
46 BrotliEncoderState* s;
47 size_t out_size = *encoded_size;
48 const uint8_t* input_start = input_buffer;
49--
502.31.1
51
diff --git a/meta/recipes-core/ovmf/ovmf/0001-ovmf-update-path-to-native-BaseTools.patch b/meta/recipes-core/ovmf/ovmf/0001-ovmf-update-path-to-native-BaseTools.patch
index 6ecb23b29f..c32963a807 100644
--- a/meta/recipes-core/ovmf/ovmf/0001-ovmf-update-path-to-native-BaseTools.patch
+++ b/meta/recipes-core/ovmf/ovmf/0001-ovmf-update-path-to-native-BaseTools.patch
@@ -1,7 +1,7 @@
1From 0a8362cfb9f00870d70687475665b131dd82c947 Mon Sep 17 00:00:00 2001 1From 200ff35c6545b4ab85f5ea7a6096fbaec3d82f6d Mon Sep 17 00:00:00 2001
2From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> 2From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
3Date: Thu, 9 Jun 2016 02:23:01 -0700 3Date: Thu, 9 Jun 2016 02:23:01 -0700
4Subject: [PATCH 1/5] ovmf: update path to native BaseTools 4Subject: [PATCH 1/4] ovmf: update path to native BaseTools
5 5
6BaseTools is a set of utilities to build EDK-based firmware. These utilities 6BaseTools is a set of utilities to build EDK-based firmware. These utilities
7are used during the build process. Thus, they need to be built natively. 7are used during the build process. Thus, they need to be built natively.
@@ -30,5 +30,5 @@ index 91b1442ade..1858dae31a 100755
30 source edksetup.sh BaseTools 30 source edksetup.sh BaseTools
31 else 31 else
32-- 32--
332.17.1 332.28.0
34 34
diff --git a/meta/recipes-core/ovmf/ovmf/0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch b/meta/recipes-core/ovmf/ovmf/0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch
index f37ed018ab..c61a08f022 100644
--- a/meta/recipes-core/ovmf/ovmf/0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch
+++ b/meta/recipes-core/ovmf/ovmf/0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch
@@ -1,7 +1,7 @@
1From a8bceaec1b16fffbf6810df05503d8ae9092b735 Mon Sep 17 00:00:00 2001 1From 667c0cf97dadc4f5994d26ec3984f559a05ec406 Mon Sep 17 00:00:00 2001
2From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> 2From: Ricardo Neri <ricardo.neri-calderon@linux.intel.com>
3Date: Fri, 26 Jul 2019 17:34:26 -0400 3Date: Fri, 26 Jul 2019 17:34:26 -0400
4Subject: [PATCH 2/5] BaseTools: makefile: adjust to build in under bitbake 4Subject: [PATCH 2/4] BaseTools: makefile: adjust to build in under bitbake
5 5
6Prepend the build flags with those of bitbake. This is to build 6Prepend the build flags with those of bitbake. This is to build
7using the bitbake native sysroot include and library directories. 7using the bitbake native sysroot include and library directories.
@@ -10,14 +10,14 @@ Signed-off-by: Ricardo Neri <ricardo.neri@linux.intel.com>
10Upstream-Status: Pending 10Upstream-Status: Pending
11 11
12--- 12---
13 BaseTools/Source/C/Makefiles/header.makefile | 10 +++++----- 13 BaseTools/Source/C/Makefiles/header.makefile | 17 +++++++++--------
14 1 file changed, 5 insertions(+), 5 deletions(-) 14 1 file changed, 9 insertions(+), 8 deletions(-)
15 15
16diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile 16diff --git a/BaseTools/Source/C/Makefiles/header.makefile b/BaseTools/Source/C/Makefiles/header.makefile
17index 4e9b36d98b..eb03ee33fa 100644 17index 1c105ee7d4..d5eea3864e 100644
18--- a/BaseTools/Source/C/Makefiles/header.makefile 18--- a/BaseTools/Source/C/Makefiles/header.makefile
19+++ b/BaseTools/Source/C/Makefiles/header.makefile 19+++ b/BaseTools/Source/C/Makefiles/header.makefile
20@@ -62,23 +62,23 @@ $(error Bad HOST_ARCH) 20@@ -69,35 +69,36 @@ $(error Bad HOST_ARCH)
21 endif 21 endif
22 22
23 INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE) 23 INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE)
@@ -33,19 +33,35 @@ index 4e9b36d98b..eb03ee33fa 100644
33+BUILD_CFLAGS += -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror \ 33+BUILD_CFLAGS += -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror \
34 -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g 34 -Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g
35 else 35 else
36 ifeq ($(CXX), llvm)
37-BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
38+BUILD_CFLAGS += -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
39 -fno-delete-null-pointer-checks -Wall -Werror \
40 -Wno-deprecated-declarations -Wno-self-assign \
41 -Wno-unused-result -nostdlib -g
42 else
36-BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \ 43-BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
37+BUILD_CFLAGS += -MD -fshort-wchar -fno-strict-aliasing -fwrapv \ 44+BUILD_CFLAGS += -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
38 -fno-delete-null-pointer-checks -Wall -Werror \ 45 -fno-delete-null-pointer-checks -Wall -Werror \
39 -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \ 46 -Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \
40 -Wno-unused-result -nostdlib -g 47 -Wno-unused-result -nostdlib -g
41 endif 48 endif
49 endif
50 ifeq ($(CXX), llvm)
51-BUILD_LFLAGS =
52-BUILD_CXXFLAGS = -Wno-deprecated-register -Wno-unused-result
53+BUILD_LFLAGS = $(LDFLAGS)
54+BUILD_CXXFLAGS += -Wno-deprecated-register -Wno-unused-result
55 else
42-BUILD_LFLAGS = 56-BUILD_LFLAGS =
43-BUILD_CXXFLAGS = -Wno-unused-result 57-BUILD_CXXFLAGS = -Wno-unused-result
44+BUILD_LFLAGS = $(LDFLAGS) 58+BUILD_LFLAGS = $(LDFLAGS)
45+BUILD_CXXFLAGS += -Wno-unused-result 59+BUILD_CXXFLAGS += -Wno-unused-result
46 60 endif
61+
47 ifeq ($(HOST_ARCH), IA32) 62 ifeq ($(HOST_ARCH), IA32)
48 # 63 #
64 # Snow Leopard is a 32-bit and 64-bit environment. uname -m returns i386, but gcc defaults
49-- 65--
502.17.1 662.28.0
51 67
diff --git a/meta/recipes-core/ovmf/ovmf/0003-ovmf-enable-long-path-file.patch b/meta/recipes-core/ovmf/ovmf/0003-ovmf-enable-long-path-file.patch
index ab1e7db31f..df1d159011 100644
--- a/meta/recipes-core/ovmf/ovmf/0003-ovmf-enable-long-path-file.patch
+++ b/meta/recipes-core/ovmf/ovmf/0003-ovmf-enable-long-path-file.patch
@@ -1,7 +1,7 @@
1From 60a5f953f747e1e9e05a40157b651cba8ea57b91 Mon Sep 17 00:00:00 2001 1From e19481e5a64f8915ac118899b10c40d12c0f9daa Mon Sep 17 00:00:00 2001
2From: Dengke Du <dengke.du@windriver.com> 2From: Dengke Du <dengke.du@windriver.com>
3Date: Mon, 11 Sep 2017 02:21:55 -0400 3Date: Mon, 11 Sep 2017 02:21:55 -0400
4Subject: [PATCH 3/5] ovmf: enable long path file 4Subject: [PATCH 3/4] ovmf: enable long path file
5 5
6Upstream-Status: Pending 6Upstream-Status: Pending
7Signed-off-by: Dengke Du <dengke.du@windriver.com> 7Signed-off-by: Dengke Du <dengke.du@windriver.com>
@@ -24,5 +24,5 @@ index e1cce985f7..d67d03c70c 100644
24 #define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL) 24 #define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
25 #define MAX_UINT32 ((UINT32)0xFFFFFFFF) 25 #define MAX_UINT32 ((UINT32)0xFFFFFFFF)
26-- 26--
272.17.1 272.28.0
28 28
diff --git a/meta/recipes-core/ovmf/ovmf/0004-ovmf-Update-to-latest.patch b/meta/recipes-core/ovmf/ovmf/0004-ovmf-Update-to-latest.patch
index c10a39d95d..128438b201 100644
--- a/meta/recipes-core/ovmf/ovmf/0004-ovmf-Update-to-latest.patch
+++ b/meta/recipes-core/ovmf/ovmf/0004-ovmf-Update-to-latest.patch
@@ -1,7 +1,7 @@
1From 94eff316b31b4d0348af28c77be5c00bc09fe8e7 Mon Sep 17 00:00:00 2001 1From ad06fcf1e08736e79221cd6863ff2e3c9254f261 Mon Sep 17 00:00:00 2001
2From: Steve Langasek <steve.langasek@ubuntu.com> 2From: Steve Langasek <steve.langasek@ubuntu.com>
3Date: Sat, 10 Jun 2017 01:39:36 -0700 3Date: Sat, 10 Jun 2017 01:39:36 -0700
4Subject: [PATCH 4/5] ovmf: Update to latest 4Subject: [PATCH 4/4] ovmf: Update to latest
5 5
6Description: pass -fno-stack-protector to all GCC toolchains 6Description: pass -fno-stack-protector to all GCC toolchains
7 The upstream build rules inexplicably pass -fno-stack-protector only 7 The upstream build rules inexplicably pass -fno-stack-protector only
@@ -15,15 +15,15 @@ Upstream-Status: Pending
15 1 file changed, 4 insertions(+), 4 deletions(-) 15 1 file changed, 4 insertions(+), 4 deletions(-)
16 16
17diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template 17diff --git a/BaseTools/Conf/tools_def.template b/BaseTools/Conf/tools_def.template
18index ca0b122dbb..b0066c2ab8 100755 18index 933b3160fd..c2fbbf0c38 100755
19--- a/BaseTools/Conf/tools_def.template 19--- a/BaseTools/Conf/tools_def.template
20+++ b/BaseTools/Conf/tools_def.template 20+++ b/BaseTools/Conf/tools_def.template
21@@ -1941,10 +1941,10 @@ DEFINE GCC_X64_RC_FLAGS = -I binary -O elf64-x86-64 -B i386 21@@ -1952,10 +1952,10 @@ DEFINE GCC_RISCV64_RC_FLAGS = -I binary -O elf64-littleriscv -B riscv
22 DEFINE GCC_ARM_RC_FLAGS = -I binary -O elf32-littlearm -B arm --rename-section .data=.hii 22 # GCC Build Flag for included header file list generation
23 DEFINE GCC_AARCH64_RC_FLAGS = -I binary -O elf64-littleaarch64 -B aarch64 --rename-section .data=.hii 23 DEFINE GCC_DEPS_FLAGS = -MMD -MF $@.deps
24 24
25-DEFINE GCC48_ALL_CC_FLAGS = -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings 25-DEFINE GCC48_ALL_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
26+DEFINE GCC48_ALL_CC_FLAGS = -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -fno-stack-protector -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings 26+DEFINE GCC48_ALL_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -fno-stack-protector -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
27 DEFINE GCC48_IA32_X64_DLINK_COMMON = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x20 27 DEFINE GCC48_IA32_X64_DLINK_COMMON = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x20
28-DEFINE GCC48_IA32_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address 28-DEFINE GCC48_IA32_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address
29-DEFINE GCC48_X64_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address 29-DEFINE GCC48_X64_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address
@@ -32,7 +32,7 @@ index ca0b122dbb..b0066c2ab8 100755
32 DEFINE GCC48_IA32_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,ReferenceAcpiTable -u ReferenceAcpiTable 32 DEFINE GCC48_IA32_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,ReferenceAcpiTable -u ReferenceAcpiTable
33 DEFINE GCC48_IA32_X64_DLINK_FLAGS = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,$(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Wl,-Map,$(DEST_DIR_DEBUG)/$(BASE_NAME).map,--whole-archive 33 DEFINE GCC48_IA32_X64_DLINK_FLAGS = DEF(GCC48_IA32_X64_DLINK_COMMON) -Wl,--entry,$(IMAGE_ENTRY_POINT) -u $(IMAGE_ENTRY_POINT) -Wl,-Map,$(DEST_DIR_DEBUG)/$(BASE_NAME).map,--whole-archive
34 DEFINE GCC48_IA32_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x220 DEF(GCC_DLINK2_FLAGS_COMMON) 34 DEFINE GCC48_IA32_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x220 DEF(GCC_DLINK2_FLAGS_COMMON)
35@@ -1953,7 +1953,7 @@ DEFINE GCC48_X64_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x228 DEF 35@@ -1964,7 +1964,7 @@ DEFINE GCC48_X64_DLINK2_FLAGS = -Wl,--defsym=PECOFF_HEADER_SIZE=0x228 DEF
36 DEFINE GCC48_ASM_FLAGS = DEF(GCC_ASM_FLAGS) 36 DEFINE GCC48_ASM_FLAGS = DEF(GCC_ASM_FLAGS)
37 DEFINE GCC48_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ASM_FLAGS) -mlittle-endian 37 DEFINE GCC48_ARM_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ASM_FLAGS) -mlittle-endian
38 DEFINE GCC48_AARCH64_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ASM_FLAGS) -mlittle-endian 38 DEFINE GCC48_AARCH64_ASM_FLAGS = $(ARCHASM_FLAGS) $(PLATFORM_FLAGS) DEF(GCC_ASM_FLAGS) -mlittle-endian
@@ -42,5 +42,5 @@ index ca0b122dbb..b0066c2ab8 100755
42 DEFINE GCC48_AARCH64_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -mcmodel=large DEF(GCC_AARCH64_CC_FLAGS) 42 DEFINE GCC48_AARCH64_CC_FLAGS = $(ARCHCC_FLAGS) $(PLATFORM_FLAGS) -mcmodel=large DEF(GCC_AARCH64_CC_FLAGS)
43 DEFINE GCC48_AARCH64_CC_XIPFLAGS = DEF(GCC_AARCH64_CC_XIPFLAGS) 43 DEFINE GCC48_AARCH64_CC_XIPFLAGS = DEF(GCC_AARCH64_CC_XIPFLAGS)
44-- 44--
452.17.1 452.28.0
46 46
diff --git a/meta/recipes-core/ovmf/ovmf_git.bb b/meta/recipes-core/ovmf/ovmf_git.bb
index 9667fa0c86..a487f77e3c 100644
--- a/meta/recipes-core/ovmf/ovmf_git.bb
+++ b/meta/recipes-core/ovmf/ovmf_git.bb
@@ -12,15 +12,19 @@ LIC_FILES_CHKSUM = "file://OvmfPkg/License.txt;md5=06357ddc23f46577c2aeaeaf7b776
12PACKAGECONFIG ??= "" 12PACKAGECONFIG ??= ""
13PACKAGECONFIG[secureboot] = ",,," 13PACKAGECONFIG[secureboot] = ",,,"
14 14
15SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=git \ 15SRC_URI = "gitsm://github.com/tianocore/edk2.git;branch=master;protocol=https \
16 file://0001-ovmf-update-path-to-native-BaseTools.patch \ 16 file://0001-ovmf-update-path-to-native-BaseTools.patch \
17 file://0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch \ 17 file://0002-BaseTools-makefile-adjust-to-build-in-under-bitbake.patch \
18 file://0003-ovmf-enable-long-path-file.patch \ 18 file://0003-ovmf-enable-long-path-file.patch \
19 file://0004-ovmf-Update-to-latest.patch \ 19 file://0004-ovmf-Update-to-latest.patch \
20 " 20 file://0001-Fix-VLA-parameter-warning.patch \
21 21 file://0001-Basetools-genffs-fix-gcc12-warning.patch \
22PV = "edk2-stable201911" 22 file://0001-Basetools-lzmaenc-fix-gcc12-warning.patch \
23SRCREV = "bd85bf54c268204c7a698a96f3ccd96cd77952cd" 23 file://0001-Basetools-turn-off-gcc12-warning.patch \
24 "
25
26PV = "edk2-stable202008"
27SRCREV = "06dc822d045c2bb42e497487935485302486e151"
24UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>edk2-stable.*)" 28UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>edk2-stable.*)"
25 29
26inherit deploy 30inherit deploy
@@ -37,7 +41,7 @@ EDK_TOOLS_DIR="edk2_basetools"
37BUILD_OPTIMIZATION="-pipe" 41BUILD_OPTIMIZATION="-pipe"
38 42
39# OVMF supports IA only, although it could conceivably support ARM someday. 43# OVMF supports IA only, although it could conceivably support ARM someday.
40COMPATIBLE_HOST='(i.86|x86_64).*' 44COMPATIBLE_HOST_class-target='(i.86|x86_64).*'
41 45
42# Additional build flags for OVMF with Secure Boot. 46# Additional build flags for OVMF with Secure Boot.
43# Fedora also uses "-D SMM_REQUIRE -D EXCLUDE_SHELL_FROM_FD". 47# Fedora also uses "-D SMM_REQUIRE -D EXCLUDE_SHELL_FROM_FD".
diff --git a/meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb b/meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb
index 5ec3f6c927..5523f874db 100644
--- a/meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb
+++ b/meta/recipes-core/packagegroups/packagegroup-core-ssh-dropbear.bb
@@ -4,3 +4,4 @@ PR = "r1"
4inherit packagegroup 4inherit packagegroup
5 5
6RDEPENDS_${PN} = "dropbear" 6RDEPENDS_${PN} = "dropbear"
7RRECOMMENDS_${PN} = "openssh-sftp-server"
diff --git a/meta/recipes-core/psplash/files/psplash-start.service b/meta/recipes-core/psplash/files/psplash-start.service
index 36c2bb38e0..bec9368427 100644
--- a/meta/recipes-core/psplash/files/psplash-start.service
+++ b/meta/recipes-core/psplash/files/psplash-start.service
@@ -2,6 +2,7 @@
2Description=Start psplash boot splash screen 2Description=Start psplash boot splash screen
3DefaultDependencies=no 3DefaultDependencies=no
4RequiresMountsFor=/run 4RequiresMountsFor=/run
5ConditionFileIsExecutable=/usr/bin/psplash
5 6
6[Service] 7[Service]
7Type=notify 8Type=notify
diff --git a/meta/recipes-core/psplash/files/psplash-systemd.service b/meta/recipes-core/psplash/files/psplash-systemd.service
index 082207f232..e93e3deb35 100644
--- a/meta/recipes-core/psplash/files/psplash-systemd.service
+++ b/meta/recipes-core/psplash/files/psplash-systemd.service
@@ -4,6 +4,7 @@ DefaultDependencies=no
4After=psplash-start.service 4After=psplash-start.service
5Requires=psplash-start.service 5Requires=psplash-start.service
6RequiresMountsFor=/run 6RequiresMountsFor=/run
7ConditionFileIsExecutable=/usr/bin/psplash
7 8
8[Service] 9[Service]
9ExecStart=/usr/bin/psplash-systemd 10ExecStart=/usr/bin/psplash-systemd
diff --git a/meta/recipes-core/psplash/psplash_git.bb b/meta/recipes-core/psplash/psplash_git.bb
index 22c71f099b..b2947c2114 100644
--- a/meta/recipes-core/psplash/psplash_git.bb
+++ b/meta/recipes-core/psplash/psplash_git.bb
@@ -10,7 +10,7 @@ SRCREV = "0a902f7cd875ccf018456451be369f05fa55f962"
10PV = "0.1+git${SRCPV}" 10PV = "0.1+git${SRCPV}"
11PR = "r15" 11PR = "r15"
12 12
13SRC_URI = "git://git.yoctoproject.org/${BPN} \ 13SRC_URI = "git://git.yoctoproject.org/${BPN};branch=master \
14 file://psplash-init \ 14 file://psplash-init \
15 file://psplash-start.service \ 15 file://psplash-start.service \
16 file://psplash-systemd.service \ 16 file://psplash-systemd.service \
diff --git a/meta/recipes-core/systemd/systemd-conf/wired.network b/meta/recipes-core/systemd/systemd-conf/wired.network
index ff807ba31f..34c20fcb24 100644
--- a/meta/recipes-core/systemd/systemd-conf/wired.network
+++ b/meta/recipes-core/systemd/systemd-conf/wired.network
@@ -1,6 +1,7 @@
1[Match] 1[Match]
2Name=en* eth* 2Name=en* eth*
3KernelCommandLine=!nfsroot 3KernelCommandLine=!nfsroot
4KernelCommandLine=!ip
4 5
5[Network] 6[Network]
6DHCP=yes 7DHCP=yes
diff --git a/meta/recipes-core/systemd/systemd-conf_244.3.bb b/meta/recipes-core/systemd/systemd-conf_244.3.bb
index d9ec023bfd..9b797a91f4 100644
--- a/meta/recipes-core/systemd/systemd-conf_244.3.bb
+++ b/meta/recipes-core/systemd/systemd-conf_244.3.bb
@@ -23,9 +23,6 @@ do_install() {
23# Based on change from YP bug 8141, OE commit 5196d7bacaef1076c361adaa2867be31759c1b52 23# Based on change from YP bug 8141, OE commit 5196d7bacaef1076c361adaa2867be31759c1b52
24do_install_append_qemuall() { 24do_install_append_qemuall() {
25 install -D -m0644 ${WORKDIR}/system.conf-qemuall ${D}${systemd_unitdir}/system.conf.d/01-${PN}.conf 25 install -D -m0644 ${WORKDIR}/system.conf-qemuall ${D}${systemd_unitdir}/system.conf.d/01-${PN}.conf
26
27 # Do not install wired.network for qemu bsps
28 rm -rf ${D}${systemd_unitdir}/network
29} 26}
30 27
31PACKAGE_ARCH = "${MACHINE_ARCH}" 28PACKAGE_ARCH = "${MACHINE_ARCH}"
diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl
index 990de1ab39..e003c860e3 100755
--- a/meta/recipes-core/systemd/systemd-systemctl/systemctl
+++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl
@@ -11,6 +11,7 @@ import re
11import sys 11import sys
12 12
13from collections import namedtuple 13from collections import namedtuple
14from itertools import chain
14from pathlib import Path 15from pathlib import Path
15 16
16version = 1.0 17version = 1.0
@@ -25,12 +26,16 @@ locations = list()
25 26
26class SystemdFile(): 27class SystemdFile():
27 """Class representing a single systemd configuration file""" 28 """Class representing a single systemd configuration file"""
28 def __init__(self, root, path): 29 def __init__(self, root, path, instance_unit_name):
29 self.sections = dict() 30 self.sections = dict()
30 self._parse(root, path) 31 self._parse(root, path)
31 dirname = os.path.basename(path.name) + ".d" 32 dirname = os.path.basename(path.name) + ".d"
32 for location in locations: 33 for location in locations:
33 for path2 in sorted((root / location / "system" / dirname).glob("*.conf")): 34 files = (root / location / "system" / dirname).glob("*.conf")
35 if instance_unit_name:
36 inst_dirname = instance_unit_name + ".d"
37 files = chain(files, (root / location / "system" / inst_dirname).glob("*.conf"))
38 for path2 in sorted(files):
34 self._parse(root, path2) 39 self._parse(root, path2)
35 40
36 def _parse(self, root, path): 41 def _parse(self, root, path):
@@ -177,12 +182,14 @@ class SystemdUnit():
177 182
178 raise SystemdUnitNotFoundError(self.root, unit) 183 raise SystemdUnitNotFoundError(self.root, unit)
179 184
180 def _process_deps(self, config, service, location, prop, dirstem): 185 def _process_deps(self, config, service, location, prop, dirstem, instance):
181 systemdir = self.root / SYSCONFDIR / "systemd" / "system" 186 systemdir = self.root / SYSCONFDIR / "systemd" / "system"
182 187
183 target = ROOT / location.relative_to(self.root) 188 target = ROOT / location.relative_to(self.root)
184 try: 189 try:
185 for dependent in config.get('Install', prop): 190 for dependent in config.get('Install', prop):
191 # expand any %i to instance (ignoring escape sequence %%)
192 dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(instance), dependent)
186 wants = systemdir / "{}.{}".format(dependent, dirstem) / service 193 wants = systemdir / "{}.{}".format(dependent, dirstem) / service
187 add_link(wants, target) 194 add_link(wants, target)
188 195
@@ -193,8 +200,11 @@ class SystemdUnit():
193 # if we're enabling an instance, first extract the actual instance 200 # if we're enabling an instance, first extract the actual instance
194 # then figure out what the template unit is 201 # then figure out what the template unit is
195 template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", self.unit) 202 template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", self.unit)
203 instance_unit_name = None
196 if template: 204 if template:
197 instance = template.group('instance') 205 instance = template.group('instance')
206 if instance != "":
207 instance_unit_name = self.unit
198 unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1) 208 unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1)
199 else: 209 else:
200 instance = None 210 instance = None
@@ -206,7 +216,7 @@ class SystemdUnit():
206 # ignore aliases 216 # ignore aliases
207 return 217 return
208 218
209 config = SystemdFile(self.root, path) 219 config = SystemdFile(self.root, path, instance_unit_name)
210 if instance == "": 220 if instance == "":
211 try: 221 try:
212 default_instance = config.get('Install', 'DefaultInstance')[0] 222 default_instance = config.get('Install', 'DefaultInstance')[0]
@@ -219,8 +229,8 @@ class SystemdUnit():
219 else: 229 else:
220 service = self.unit 230 service = self.unit
221 231
222 self._process_deps(config, service, path, 'WantedBy', 'wants') 232 self._process_deps(config, service, path, 'WantedBy', 'wants', instance)
223 self._process_deps(config, service, path, 'RequiredBy', 'requires') 233 self._process_deps(config, service, path, 'RequiredBy', 'requires', instance)
224 234
225 try: 235 try:
226 for also in config.get('Install', 'Also'): 236 for also in config.get('Install', 'Also'):
diff --git a/meta/recipes-core/systemd/systemd.inc b/meta/recipes-core/systemd/systemd.inc
index 3165d13f03..8b5260bb0d 100644
--- a/meta/recipes-core/systemd/systemd.inc
+++ b/meta/recipes-core/systemd/systemd.inc
@@ -16,6 +16,6 @@ LIC_FILES_CHKSUM = "file://LICENSE.GPL2;md5=751419260aa954499f7abaabaa882bbe \
16 16
17SRCREV = "3ceaa81c61b654ebf562464d142675bd4d57d7b6" 17SRCREV = "3ceaa81c61b654ebf562464d142675bd4d57d7b6"
18SRCBRANCH = "v244-stable" 18SRCBRANCH = "v244-stable"
19SRC_URI = "git://github.com/systemd/systemd-stable.git;protocol=git;branch=${SRCBRANCH}" 19SRC_URI = "git://github.com/systemd/systemd-stable.git;protocol=https;branch=${SRCBRANCH}"
20 20
21S = "${WORKDIR}/git" 21S = "${WORKDIR}/git"
diff --git a/meta/recipes-core/systemd/systemd/00-create-volatile.conf b/meta/recipes-core/systemd/systemd/00-create-volatile.conf
index 87cbe1e7d3..c4277221a2 100644
--- a/meta/recipes-core/systemd/systemd/00-create-volatile.conf
+++ b/meta/recipes-core/systemd/systemd/00-create-volatile.conf
@@ -3,5 +3,6 @@
3# inside /var/log. 3# inside /var/log.
4 4
5 5
6d /run/lock 1777 - - -
6d /var/volatile/log - - - - 7d /var/volatile/log - - - -
7d /var/volatile/tmp 1777 - - 8d /var/volatile/tmp 1777 - -
diff --git a/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch b/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch
new file mode 100644
index 0000000000..8d3801a248
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2018-21029.patch
@@ -0,0 +1,120 @@
1From 3f9d9289ee8730a81a0464539f4e1ba2d23d0ce9 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
3Date: Tue, 3 Mar 2020 23:31:25 +0000
4Subject: [PATCH] systemd-resolved: use hostname for certificate validation in
5 DoT
6
7Widely accepted certificates for IP addresses are expensive and only
8affordable for larger organizations. Therefore if the user provides
9the hostname in the DNS= option, we should use it instead of the IP
10address.
11
12(cherry picked from commit eec394f10bbfcc3d2fc8504ad8ff5be44231abd5)
13
14CVE: CVE-2018-21029
15Upstream-Status: Backport [ff26d281aec0877b43269f18c6282cd79a7f5529]
16Signed-off-by: Marek Vasut <marex@denx.de>
17---
18 man/resolved.conf.xml | 16 +++++++++++-----
19 src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++--------
20 src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++----
21 3 files changed, 34 insertions(+), 17 deletions(-)
22
23diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
24index 818000145b..37161ebcbc 100644
25--- a/man/resolved.conf.xml
26+++ b/man/resolved.conf.xml
27@@ -193,11 +193,17 @@
28 <varlistentry>
29 <term><varname>DNSOverTLS=</varname></term>
30 <listitem>
31- <para>Takes a boolean argument or <literal>opportunistic</literal>.
32- If true all connections to the server will be encrypted. Note that
33- this mode requires a DNS server that supports DNS-over-TLS and has
34- a valid certificate for it's IP. If the DNS server does not support
35- DNS-over-TLS all DNS requests will fail. When set to <literal>opportunistic</literal>
36+ <para>Takes a boolean argument or <literal>opportunistic</literal>. If
37+ true all connections to the server will be encrypted. Note that this
38+ mode requires a DNS server that supports DNS-over-TLS and has a valid
39+ certificate. If the hostname was specified in <varname>DNS=</varname>
40+ by using the format format <literal>address#server_name</literal> it
41+ is used to validate its certificate and also to enable Server Name
42+ Indication (SNI) when opening a TLS connection. Otherwise
43+ the certificate is checked against the server's IP.
44+ If the DNS server does not support DNS-over-TLS all DNS requests will fail.</para>
45+
46+ <para>When set to <literal>opportunistic</literal>
47 DNS request are attempted to send encrypted with DNS-over-TLS.
48 If the DNS server does not support TLS, DNS-over-TLS is disabled.
49 Note that this mode makes DNS-over-TLS vulnerable to "downgrade"
50diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
51index ed0a31e8bf..c7215723a7 100644
52--- a/src/resolve/resolved-dnstls-gnutls.c
53+++ b/src/resolve/resolved-dnstls-gnutls.c
54@@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
55 }
56
57 if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
58- stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
59- if (server->family == AF_INET) {
60- stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
61- stream->dnstls_data.validation.size = 4;
62- } else {
63- stream->dnstls_data.validation.data = server->address.in6.s6_addr;
64- stream->dnstls_data.validation.size = 16;
65+ if (server->server_name)
66+ gnutls_session_set_verify_cert(gs, server->server_name, 0);
67+ else {
68+ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
69+ if (server->family == AF_INET) {
70+ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
71+ stream->dnstls_data.validation.size = 4;
72+ } else {
73+ stream->dnstls_data.validation.data = server->address.in6.s6_addr;
74+ stream->dnstls_data.validation.size = 16;
75+ }
76+ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
77 }
78- gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
79 }
80
81 gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
82diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
83index 85e202ff74..007aedaa5b 100644
84--- a/src/resolve/resolved-dnstls-openssl.c
85+++ b/src/resolve/resolved-dnstls-openssl.c
86@@ -6,6 +6,7 @@
87
88 #include <openssl/bio.h>
89 #include <openssl/err.h>
90+#include <openssl/x509v3.h>
91
92 #include "io-util.h"
93 #include "resolved-dns-stream.h"
94@@ -78,13 +79,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
95
96 if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
97 X509_VERIFY_PARAM *v;
98- const unsigned char *ip;
99
100 SSL_set_verify(s, SSL_VERIFY_PEER, NULL);
101 v = SSL_get0_param(s);
102- ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr;
103- if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)))
104- return -ECONNREFUSED;
105+ if (server->server_name) {
106+ X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
107+ if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0)
108+ return -ECONNREFUSED;
109+ } else {
110+ const unsigned char *ip;
111+ ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr;
112+ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0)
113+ return -ECONNREFUSED;
114+ }
115 }
116
117 ERR_clear_error();
118--
1192.40.1
120
diff --git a/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch b/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch
new file mode 100644
index 0000000000..6b499efbd8
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2020-13529.patch
@@ -0,0 +1,42 @@
1From 38e980a6a5a3442c2f48b1f827284388096d8ca5 Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Thu, 24 Jun 2021 01:22:07 +0900
4Subject: [PATCH] sd-dhcp-client: tentatively ignore FORCERENEW command
5
6This makes DHCP client ignore FORCERENEW requests, as unauthenticated
7FORCERENEW requests causes a security issue (TALOS-2020-1142, CVE-2020-13529).
8
9Let's re-enable this after RFC3118 (Authentication for DHCP Messages)
10and/or RFC6704 (Forcerenew Nonce Authentication) are implemented.
11
12Fixes #16774.
13
14Upstream-Status: Backport [https://github.com/systemd/systemd/commit/38e980a6a5a3442c2f48b1f827284388096d8ca5]
15CVE: CVE-2020-13529
16
17Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
18
19---
20 src/libsystemd-network/sd-dhcp-client.c | 8 ++++++++
21 1 file changed, 8 insertions(+)
22
23--- a/src/libsystemd-network/sd-dhcp-client.c
24+++ b/src/libsystemd-network/sd-dhcp-client.c
25@@ -1392,9 +1392,17 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
26 if (r != DHCP_FORCERENEW)
27 return -ENOMSG;
28
29+#if 0
30 log_dhcp_client(client, "FORCERENEW");
31
32 return 0;
33+#else
34+ /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP
35+ * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW
36+ * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */
37+ log_dhcp_client(client, "Received FORCERENEW, ignoring.");
38+ return -ENOMSG;
39+#endif
40 }
41
42 static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) {
diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch b/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch
new file mode 100644
index 0000000000..e92d721d3d
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2021-33910.patch
@@ -0,0 +1,67 @@
1Backport of:
2
3From 441e0115646d54f080e5c3bb0ba477c892861ab9 Mon Sep 17 00:00:00 2001
4From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
5Date: Wed, 23 Jun 2021 11:46:41 +0200
6Subject: [PATCH 1/2] basic/unit-name: do not use strdupa() on a path
7
8The path may have unbounded length, for example through a fuse mount.
9
10CVE-2021-33910: attacked controlled alloca() leads to crash in systemd and
11ultimately a kernel panic. Systemd parses the content of /proc/self/mountinfo
12and each mountpoint is passed to mount_setup_unit(), which calls
13unit_name_path_escape() underneath. A local attacker who is able to mount a
14filesystem with a very long path can crash systemd and the whole system.
15
16https://bugzilla.redhat.com/show_bug.cgi?id=1970887
17
18The resulting string length is bounded by UNIT_NAME_MAX, which is 256. But we
19can't easily check the length after simplification before doing the
20simplification, which in turns uses a copy of the string we can write to.
21So we can't reject paths that are too long before doing the duplication.
22Hence the most obvious solution is to switch back to strdup(), as before
237410616cd9dbbec97cf98d75324da5cda2b2f7a2.
24
25Upstream-Status: Backport [https://github.com/systemd/systemd/pull/20256/commits/441e0115646d54f080e5c3bb0ba477c892861ab9]
26CVE: CVE-2021-33910
27
28Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
29
30---
31 src/basic/unit-name.c | 13 +++++--------
32 1 file changed, 5 insertions(+), 8 deletions(-)
33
34--- a/src/basic/unit-name.c
35+++ b/src/basic/unit-name.c
36@@ -369,12 +369,13 @@ int unit_name_unescape(const char *f, char **ret) {
37 }
38
39 int unit_name_path_escape(const char *f, char **ret) {
40- char *p, *s;
41+ _cleanup_free_ char *p = NULL;
42+ char *s;
43
44 assert(f);
45 assert(ret);
46
47- p = strdupa(f);
48+ p = strdup(f);
49 if (!p)
50 return -ENOMEM;
51
52@@ -386,13 +387,9 @@ int unit_name_path_escape(const char *f, char **ret) {
53 if (!path_is_normalized(p))
54 return -EINVAL;
55
56- /* Truncate trailing slashes */
57+ /* Truncate trailing slashes and skip leading slashes */
58 delete_trailing_chars(p, "/");
59-
60- /* Truncate leading slashes */
61- p = skip_leading_chars(p, "/");
62-
63- s = unit_name_escape(p);
64+ s = unit_name_escape(skip_leading_chars(p, "/"));
65 }
66 if (!s)
67 return -ENOMEM;
diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch
new file mode 100644
index 0000000000..341976822b
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-1.patch
@@ -0,0 +1,65 @@
1Backport of the following upstream commit:
2From fbb77e1e55866633c9f064e2b3bcf2b6402d962d Mon Sep 17 00:00:00 2001
3From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
4Date: Tue, 23 Nov 2021 15:55:45 +0100
5Subject: [PATCH 1/3] shared/rm_rf: refactor rm_rf_children_inner() to shorten
6 code a bit
7
8CVE: CVE-2021-3997
9Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz]
10Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
11---
12 src/basic/rm-rf.c | 27 +++++++++------------------
13 1 file changed, 9 insertions(+), 18 deletions(-)
14
15--- a/src/basic/rm-rf.c
16+++ b/src/basic/rm-rf.c
17@@ -34,7 +34,7 @@
18 const struct stat *root_dev) {
19
20 struct stat st;
21- int r;
22+ int r, q = 0;
23
24 assert(fd >= 0);
25 assert(fname);
26@@ -50,7 +50,6 @@
27
28 if (is_dir) {
29 _cleanup_close_ int subdir_fd = -1;
30- int q;
31
32 /* if root_dev is set, remove subdirectories only if device is same */
33 if (root_dev && st.st_dev != root_dev->st_dev)
34@@ -86,23 +85,15 @@
35 * again for each directory */
36 q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
37
38- r = unlinkat(fd, fname, AT_REMOVEDIR);
39- if (r < 0)
40- return r;
41- if (q < 0)
42- return q;
43-
44- return 1;
45-
46- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
47- r = unlinkat(fd, fname, 0);
48- if (r < 0)
49- return r;
50-
51- return 1;
52- }
53+ } else if (flags & REMOVE_ONLY_DIRECTORIES)
54+ return 0;
55
56- return 0;
57+ r = unlinkat(fd, fname, is_dir ? AT_REMOVEDIR : 0);
58+ if (r < 0)
59+ return r;
60+ if (q < 0)
61+ return q;
62+ return 1;
63 }
64
65 int rm_rf_children(
diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch
new file mode 100644
index 0000000000..066e10fbbc
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-2.patch
@@ -0,0 +1,101 @@
1Backport of the following upstream commit:
2From bd0127daaaae009ade053718f7d2f297aee4acaf Mon Sep 17 00:00:00 2001
3From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
4Date: Tue, 23 Nov 2021 16:56:42 +0100
5Subject: [PATCH 2/3] shared/rm_rf: refactor rm_rf() to shorten code a bit
6
7CVE: CVE-2021-3997
8Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz]
9Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
10---
11 src/basic/rm-rf.c | 53 ++++++++++++++++++++--------------------------
12 1 file changed, 23 insertions(+), 30 deletions(-)
13
14--- a/src/basic/rm-rf.c
15+++ b/src/basic/rm-rf.c
16@@ -159,7 +159,7 @@
17 }
18
19 int rm_rf(const char *path, RemoveFlags flags) {
20- int fd, r;
21+ int fd, r, q = 0;
22
23 assert(path);
24
25@@ -191,49 +191,47 @@
26 }
27
28 fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
29- if (fd < 0) {
30+ if (fd >= 0) {
31+ /* We have a dir */
32+ r = rm_rf_children(fd, flags, NULL);
33+
34+ if (FLAGS_SET(flags, REMOVE_ROOT)) {
35+ q = rmdir(path);
36+ if (q < 0)
37+ q = -errno;
38+ }
39+ } else {
40 if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT)
41 return 0;
42
43 if (!IN_SET(errno, ENOTDIR, ELOOP))
44 return -errno;
45
46- if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES))
47+ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES) || !FLAGS_SET(flags, REMOVE_ROOT))
48 return 0;
49
50- if (FLAGS_SET(flags, REMOVE_ROOT)) {
51-
52- if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) {
53- struct statfs s;
54-
55- if (statfs(path, &s) < 0)
56- return -errno;
57- if (is_physical_fs(&s))
58- return log_error_errno(SYNTHETIC_ERRNO(EPERM),
59- "Attempted to remove files from a disk file system under \"%s\", refusing.",
60- path);
61- }
62-
63- if (unlink(path) < 0) {
64- if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT)
65- return 0;
66+ if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) {
67+ struct statfs s;
68
69+ if (statfs(path, &s) < 0)
70 return -errno;
71- }
72+ if (is_physical_fs(&s))
73+ return log_error_errno(SYNTHETIC_ERRNO(EPERM),
74+ "Attempted to remove files from a disk file system under \"%s\", refusing.",
75+ path);
76 }
77
78- return 0;
79+ r = 0;
80+ q = unlink(path);
81+ if (q < 0)
82+ q = -errno;
83 }
84
85- r = rm_rf_children(fd, flags, NULL);
86-
87- if (FLAGS_SET(flags, REMOVE_ROOT) &&
88- rmdir(path) < 0 &&
89- r >= 0 &&
90- (!FLAGS_SET(flags, REMOVE_MISSING_OK) || errno != ENOENT))
91- r = -errno;
92-
93- return r;
94+ if (r < 0)
95+ return r;
96+ if (q < 0 && (q != -ENOENT || !FLAGS_SET(flags, REMOVE_MISSING_OK)))
97+ return q;
98+ return 0;
99 }
100
101 int rm_rf_child(int fd, const char *name, RemoveFlags flags) {
diff --git a/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch b/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch
new file mode 100644
index 0000000000..c96b8d9a6e
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2021-3997-3.patch
@@ -0,0 +1,266 @@
1Backport of the following upstream commit:
2From bef8e8e577368697b2e6f85183b1dbc99e0e520f Mon Sep 17 00:00:00 2001
3From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
4Date: Tue, 30 Nov 2021 22:29:05 +0100
5Subject: [PATCH 3/3] shared/rm-rf: loop over nested directories instead of
6 instead of recursing
7
8To remove directory structures, we need to remove the innermost items first,
9and then recursively remove higher-level directories. We would recursively
10descend into directories and invoke rm_rf_children and rm_rm_children_inner.
11This is problematic when too many directories are nested.
12
13Instead, let's create a "TODO" queue. In the the queue, for each level we
14hold the DIR* object we were working on, and the name of the directory. This
15allows us to leave a partially-processed directory, and restart the removal
16loop one level down. When done with the inner directory, we use the name to
17unlinkat() it from the parent, and proceed with the removal of other items.
18
19Because the nesting is increased by one level, it is best to view this patch
20with -b/--ignore-space-change.
21
22This fixes CVE-2021-3997, https://bugzilla.redhat.com/show_bug.cgi?id=2024639.
23The issue was reported and patches reviewed by Qualys Team.
24Mauro Matteo Cascella and Riccardo Schirone from Red Hat handled the disclosure.
25
26CVE: CVE-2021-3997
27Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz]
28Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
29---
30 src/basic/rm-rf.c | 161 +++++++++++++++++++++++++++++++--------------
31 1 file changed, 113 insertions(+), 48 deletions(-)
32
33--- a/src/basic/rm-rf.c
34+++ b/src/basic/rm-rf.c
35@@ -26,12 +26,13 @@
36 return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs);
37 }
38
39-static int rm_rf_children_inner(
40+static int rm_rf_inner_child(
41 int fd,
42 const char *fname,
43 int is_dir,
44 RemoveFlags flags,
45- const struct stat *root_dev) {
46+ const struct stat *root_dev,
47+ bool allow_recursion) {
48
49 struct stat st;
50 int r, q = 0;
51@@ -49,9 +50,7 @@
52 }
53
54 if (is_dir) {
55- _cleanup_close_ int subdir_fd = -1;
56-
57- /* if root_dev is set, remove subdirectories only if device is same */
58+ /* If root_dev is set, remove subdirectories only if device is same */
59 if (root_dev && st.st_dev != root_dev->st_dev)
60 return 0;
61
62@@ -63,7 +62,6 @@
63 return 0;
64
65 if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
66-
67 /* This could be a subvolume, try to remove it */
68
69 r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
70@@ -77,13 +75,16 @@
71 return 1;
72 }
73
74- subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
75+ if (!allow_recursion)
76+ return -EISDIR;
77+
78+ int subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
79 if (subdir_fd < 0)
80 return -errno;
81
82 /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type
83 * again for each directory */
84- q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
85+ q = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev);
86
87 } else if (flags & REMOVE_ONLY_DIRECTORIES)
88 return 0;
89@@ -96,64 +97,128 @@
90 return 1;
91 }
92
93+typedef struct TodoEntry {
94+ DIR *dir; /* A directory that we were operating on. */
95+ char *dirname; /* The filename of that directory itself. */
96+} TodoEntry;
97+
98+static void free_todo_entries(TodoEntry **todos) {
99+ for (TodoEntry *x = *todos; x && x->dir; x++) {
100+ closedir(x->dir);
101+ free(x->dirname);
102+ }
103+
104+ freep(todos);
105+}
106+
107 int rm_rf_children(
108 int fd,
109 RemoveFlags flags,
110 const struct stat *root_dev) {
111
112- _cleanup_closedir_ DIR *d = NULL;
113- struct dirent *de;
114+ _cleanup_(free_todo_entries) TodoEntry *todos = NULL;
115+ size_t n_todo = 0, allocated = 0;
116+ _cleanup_free_ char *dirname = NULL; /* Set when we are recursing and want to delete ourselves */
117 int ret = 0, r;
118
119- assert(fd >= 0);
120+ /* Return the first error we run into, but nevertheless try to go on.
121+ * The passed fd is closed in all cases, including on failure. */
122
123- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed
124- * fd, in all cases, including on failure. */
125+ for (;;) { /* This loop corresponds to the directory nesting level. */
126+ _cleanup_closedir_ DIR *d = NULL;
127+ struct dirent *de;
128+
129+ if (n_todo > 0) {
130+ /* We know that we are in recursion here, because n_todo is set.
131+ * We need to remove the inner directory we were operating on. */
132+ assert(dirname);
133+ r = unlinkat(dirfd(todos[n_todo-1].dir), dirname, AT_REMOVEDIR);
134+ if (r < 0 && r != -ENOENT && ret == 0)
135+ ret = r;
136+ dirname = mfree(dirname);
137+
138+ /* And now let's back out one level up */
139+ n_todo --;
140+ d = TAKE_PTR(todos[n_todo].dir);
141+ dirname = TAKE_PTR(todos[n_todo].dirname);
142+
143+ assert(d);
144+ fd = dirfd(d); /* Retrieve the file descriptor from the DIR object */
145+ assert(fd >= 0);
146+ } else {
147+ next_fd:
148+ assert(fd >= 0);
149+ d = fdopendir(fd);
150+ if (!d) {
151+ safe_close(fd);
152+ return -errno;
153+ }
154+ fd = dirfd(d); /* We donated the fd to fdopendir(). Let's make sure we sure we have
155+ * the right descriptor even if it were to internally invalidate the
156+ * one we passed. */
157+
158+ if (!(flags & REMOVE_PHYSICAL)) {
159+ struct statfs sfs;
160+
161+ if (fstatfs(fd, &sfs) < 0)
162+ return -errno;
163+
164+ if (is_physical_fs(&sfs)) {
165+ /* We refuse to clean physical file systems with this call, unless
166+ * explicitly requested. This is extra paranoia just to be sure we
167+ * never ever remove non-state data. */
168+
169+ _cleanup_free_ char *path = NULL;
170+
171+ (void) fd_get_path(fd, &path);
172+ return log_error_errno(SYNTHETIC_ERRNO(EPERM),
173+ "Attempted to remove disk file system under \"%s\", and we can't allow that.",
174+ strna(path));
175+ }
176+ }
177+ }
178
179- d = fdopendir(fd);
180- if (!d) {
181- safe_close(fd);
182- return -errno;
183- }
184+ FOREACH_DIRENT_ALL(de, d, return -errno) {
185+ int is_dir;
186
187- if (!(flags & REMOVE_PHYSICAL)) {
188- struct statfs sfs;
189+ if (dot_or_dot_dot(de->d_name))
190+ continue;
191
192- if (fstatfs(dirfd(d), &sfs) < 0)
193- return -errno;
194- }
195+ is_dir = de->d_type == DT_UNKNOWN ? -1 : de->d_type == DT_DIR;
196
197- if (is_physical_fs(&sfs)) {
198- /* We refuse to clean physical file systems with this call, unless explicitly
199- * requested. This is extra paranoia just to be sure we never ever remove non-state
200- * data. */
201-
202- _cleanup_free_ char *path = NULL;
203-
204- (void) fd_get_path(fd, &path);
205- return log_error_errno(SYNTHETIC_ERRNO(EPERM),
206- "Attempted to remove disk file system under \"%s\", and we can't allow that.",
207- strna(path));
208- }
209- }
210+ r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, false);
211+ if (r == -EISDIR) {
212+ /* Push the current working state onto the todo list */
213
214- FOREACH_DIRENT_ALL(de, d, return -errno) {
215- int is_dir;
216+ if (!GREEDY_REALLOC0(todos, allocated, n_todo + 2))
217+ return log_oom();
218
219- if (dot_or_dot_dot(de->d_name))
220- continue;
221+ _cleanup_free_ char *newdirname = strdup(de->d_name);
222+ if (!newdirname)
223+ return log_oom();
224
225- is_dir =
226- de->d_type == DT_UNKNOWN ? -1 :
227- de->d_type == DT_DIR;
228-
229- r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev);
230- if (r < 0 && r != -ENOENT && ret == 0)
231- ret = r;
232- }
233+ int newfd = openat(fd, de->d_name,
234+ O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
235+ if (newfd >= 0) {
236+ todos[n_todo++] = (TodoEntry) { TAKE_PTR(d), TAKE_PTR(dirname) };
237+ fd = newfd;
238+ dirname = TAKE_PTR(newdirname);
239+
240+ goto next_fd;
241
242- if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0)
243- ret = -errno;
244+ } else if (errno != -ENOENT && ret == 0)
245+ ret = -errno;
246+
247+ } else if (r < 0 && r != -ENOENT && ret == 0)
248+ ret = r;
249+ }
250+
251+ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(fd) < 0 && ret >= 0)
252+ ret = -errno;
253+
254+ if (n_todo == 0)
255+ break;
256+ }
257
258 return ret;
259 }
260@@ -250,5 +315,5 @@
261 if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME))
262 return -EINVAL;
263
264- return rm_rf_children_inner(fd, name, -1, flags, NULL);
265+ return rm_rf_inner_child(fd, name, -1, flags, NULL, true);
266 }
diff --git a/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch b/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch
new file mode 100644
index 0000000000..f9c6704cfc
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2022-3821.patch
@@ -0,0 +1,47 @@
1From 9102c625a673a3246d7e73d8737f3494446bad4e Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Thu, 7 Jul 2022 18:27:02 +0900
4Subject: [PATCH] time-util: fix buffer-over-run
5
6Fixes #23928.
7
8CVE: CVE-2022-3821
9Upstream-Status: Backport [https://github.com/systemd/systemd/commit/9102c625a673a3246d7e73d8737f3494446bad4e.patch]
10Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
11Comment: Both the hunks refreshed to backport
12
13---
14 src/basic/time-util.c | 2 +-
15 src/test/test-time-util.c | 5 +++++
16 2 files changed, 6 insertions(+), 1 deletion(-)
17
18diff --git a/src/basic/time-util.c b/src/basic/time-util.c
19index abbc4ad5cd70..26d59de12348 100644
20--- a/src/basic/time-util.c
21+++ b/src/basic/time-util.c
22@@ -514,7 +514,7 @@ char *format_timespan(char *buf, size_t
23 t = b;
24 }
25
26- n = MIN((size_t) k, l);
27+ n = MIN((size_t) k, l-1);
28
29 l -= n;
30 p += n;
31diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c
32index e8e4e2a67bb1..58c5fa9be40c 100644
33--- a/src/test/test-time-util.c
34+++ b/src/test/test-time-util.c
35@@ -501,6 +501,12 @@ int main(int argc, char *argv[]) {
36 test_format_timespan(1);
37 test_format_timespan(USEC_PER_MSEC);
38 test_format_timespan(USEC_PER_SEC);
39+
40+ /* See issue #23928. */
41+ _cleanup_free_ char *buf;
42+ assert_se(buf = new(char, 5));
43+ assert_se(buf == format_timespan(buf, 5, 100005, 1000));
44+
45 test_timezone_is_valid();
46 test_get_timezones();
47 test_usec_add();
diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch
new file mode 100644
index 0000000000..39f9480cf8
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-1.patch
@@ -0,0 +1,115 @@
1From 612ebf6c913dd0e4197c44909cb3157f5c51a2f0 Mon Sep 17 00:00:00 2001
2From: Lennart Poettering <lennart@poettering.net>
3Date: Mon, 31 Aug 2020 19:37:13 +0200
4Subject: [PATCH] pager: set $LESSSECURE whenver we invoke a pager
5
6Some extra safety when invoked via "sudo". With this we address a
7genuine design flaw of sudo, and we shouldn't need to deal with this.
8But it's still a good idea to disable this surface given how exotic it
9is.
10
11Prompted by #5666
12
13CVE: CVE-2023-26604
14Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/612ebf6c913dd0e4197c44909cb3157f5c51a2f0]
15Comments: Hunk not refreshed
16Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
17---
18 man/less-variables.xml | 9 +++++++++
19 man/systemctl.xml | 1 +
20 man/systemd.xml | 1 +
21 src/shared/pager.c | 23 +++++++++++++++++++++--
22 4 files changed, 32 insertions(+), 2 deletions(-)
23
24diff --git a/man/less-variables.xml b/man/less-variables.xml
25index 08e513c99f8e..c52511ca8e18 100644
26--- a/man/less-variables.xml
27+++ b/man/less-variables.xml
28@@ -64,6 +64,15 @@
29 the invoking terminal is determined to be UTF-8 compatible).</para></listitem>
30 </varlistentry>
31
32+ <varlistentry id='lesssecure'>
33+ <term><varname>$SYSTEMD_LESSSECURE</varname></term>
34+
35+ <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment
36+ variable when invoking the pager, which controls the "secure" mode of less (which disables commands
37+ such as <literal>|</literal> which allow to easily shell out to external command lines). By default
38+ less secure mode is enabled, with this setting it may be disabled.</para></listitem>
39+ </varlistentry>
40+
41 <varlistentry id='colors'>
42 <term><varname>$SYSTEMD_COLORS</varname></term>
43
44diff --git a/man/systemctl.xml b/man/systemctl.xml
45index 1c5502883700..a3f0c3041a57 100644
46--- a/man/systemctl.xml
47+++ b/man/systemctl.xml
48@@ -2240,6 +2240,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
49 <xi:include href="less-variables.xml" xpointer="pager"/>
50 <xi:include href="less-variables.xml" xpointer="less"/>
51 <xi:include href="less-variables.xml" xpointer="lesscharset"/>
52+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
53 <xi:include href="less-variables.xml" xpointer="colors"/>
54 <xi:include href="less-variables.xml" xpointer="urlify"/>
55 </refsect1>
56diff --git a/man/systemd.xml b/man/systemd.xml
57index a9040545c2ab..c92cfef77689 100644
58--- a/man/systemd.xml
59+++ b/man/systemd.xml
60@@ -692,6 +692,7 @@
61 <xi:include href="less-variables.xml" xpointer="pager"/>
62 <xi:include href="less-variables.xml" xpointer="less"/>
63 <xi:include href="less-variables.xml" xpointer="lesscharset"/>
64+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
65 <xi:include href="less-variables.xml" xpointer="colors"/>
66 <xi:include href="less-variables.xml" xpointer="urlify"/>
67
68diff --git a/src/shared/pager.c b/src/shared/pager.c
69index e03be6d23b2d..9c21881241f5 100644
70--- a/src/shared/pager.c
71+++ b/src/shared/pager.c
72@@ -9,6 +9,7 @@
73 #include <unistd.h>
74
75 #include "copy.h"
76+#include "env-util.h"
77 #include "fd-util.h"
78 #include "fileio.h"
79 #include "io-util.h"
80@@ -152,8 +153,7 @@ int pager_open(PagerFlags flags) {
81 _exit(EXIT_FAILURE);
82 }
83
84- /* Initialize a good charset for less. This is
85- * particularly important if we output UTF-8
86+ /* Initialize a good charset for less. This is particularly important if we output UTF-8
87 * characters. */
88 less_charset = getenv("SYSTEMD_LESSCHARSET");
89 if (!less_charset && is_locale_utf8())
90@@ -164,6 +164,25 @@ int pager_open(PagerFlags flags) {
91 _exit(EXIT_FAILURE);
92 }
93
94+ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out
95+ * privileged stuff. */
96+ r = getenv_bool("SYSTEMD_LESSSECURE");
97+ if (r == 0) { /* Remove env var if off */
98+ if (unsetenv("LESSSECURE") < 0) {
99+ log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m");
100+ _exit(EXIT_FAILURE);
101+ }
102+ } else {
103+ /* Set env var otherwise */
104+ if (r < 0)
105+ log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m");
106+
107+ if (setenv("LESSSECURE", "1", 1) < 0) {
108+ log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m");
109+ _exit(EXIT_FAILURE);
110+ }
111+ }
112+
113 if (pager_args) {
114 r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false);
115 if (r < 0) {
diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch
new file mode 100644
index 0000000000..95da7cfad6
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-2.patch
@@ -0,0 +1,264 @@
1From 1b5b507cd2d1d7a2b053151abb548475ad9c5c3b Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Mon, 12 Oct 2020 18:57:32 +0200
4Subject: [PATCH] test-login: always test sd_pid_get_owner_uid(), modernize
5
6A long time some function only worked when in a session, and the test
7didn't execute them when sd_pid_get_session() failed. Let's always call
8them to increase coverage.
9
10While at it, let's test for ==0 not >=0 where we don't expect the function
11to return anything except 0 or error.
12
13CVE: CVE-2023-26604
14Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/1b5b507cd2d1d7a2b053151abb548475ad9c5c3b.patch]
15Comments: Hunk not refreshed
16Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
17---
18 src/libsystemd/sd-login/test-login.c | 131 ++++++++++++++-------------
19 1 file changed, 70 insertions(+), 61 deletions(-)
20
21diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
22index c0c77e04714b..0494fc77ba18 100644
23--- a/src/libsystemd/sd-login/test-login.c
24+++ b/src/libsystemd/sd-login/test-login.c
25@@ -5,21 +5,22 @@
26 #include "sd-login.h"
27
28 #include "alloc-util.h"
29+#include "errno-list.h"
30 #include "fd-util.h"
31 #include "format-util.h"
32 #include "log.h"
33 #include "string-util.h"
34 #include "strv.h"
35 #include "time-util.h"
36-#include "util.h"
37+#include "user-util.h"
38
39 static char* format_uids(char **buf, uid_t* uids, int count) {
40- int pos = 0, k, inc;
41+ int pos = 0, inc;
42 size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1;
43
44 assert_se(*buf = malloc(size));
45
46- for (k = 0; k < count; k++) {
47+ for (int k = 0; k < count; k++) {
48 sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc);
49 pos += inc;
50 }
51@@ -30,6 +31,10 @@ static char* format_uids(char **buf, uid_t* uids, int count) {
52 return *buf;
53 }
54
55+static const char *e(int r) {
56+ return r == 0 ? "OK" : errno_to_name(r);
57+}
58+
59 static void test_login(void) {
60 _cleanup_close_pair_ int pair[2] = { -1, -1 };
61 _cleanup_free_ char *pp = NULL, *qq = NULL,
62@@ -39,65 +44,71 @@ static void test_login(void) {
63 *seat = NULL, *session = NULL,
64 *unit = NULL, *user_unit = NULL, *slice = NULL;
65 int r;
66- uid_t u, u2;
67- char *t, **seats, **sessions;
68+ uid_t u, u2 = UID_INVALID;
69+ char *t, **seats = NULL, **sessions = NULL;
70
71 r = sd_pid_get_unit(0, &unit);
72- assert_se(r >= 0 || r == -ENODATA);
73- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit));
74+ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit));
75+ assert_se(IN_SET(r, 0, -ENODATA));
76
77 r = sd_pid_get_user_unit(0, &user_unit);
78- assert_se(r >= 0 || r == -ENODATA);
79- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit));
80+ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit));
81+ assert_se(IN_SET(r, 0, -ENODATA));
82
83 r = sd_pid_get_slice(0, &slice);
84- assert_se(r >= 0 || r == -ENODATA);
85- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice));
86+ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice));
87+ assert_se(IN_SET(r, 0, -ENODATA));
88+
89+ r = sd_pid_get_owner_uid(0, &u2);
90+ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2);
91+ assert_se(IN_SET(r, 0, -ENODATA));
92
93 r = sd_pid_get_session(0, &session);
94- if (r < 0) {
95- log_warning_errno(r, "sd_pid_get_session(0, …): %m");
96- if (r == -ENODATA)
97- log_info("Seems we are not running in a session, skipping some tests.");
98- } else {
99- log_info("sd_pid_get_session(0, …) → \"%s\"", session);
100-
101- assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
102- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2);
103-
104- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
105- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup);
106-
107- r = sd_uid_get_display(u2, &display_session);
108- assert_se(r >= 0 || r == -ENODATA);
109- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"",
110- u2, strnull(display_session));
111-
112- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
113- sd_peer_get_session(pair[0], &pp);
114- sd_peer_get_session(pair[1], &qq);
115- assert_se(streq_ptr(pp, qq));
116-
117- r = sd_uid_get_sessions(u2, false, &sessions);
118+ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session));
119+
120+ r = sd_pid_get_cgroup(0, &cgroup);
121+ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
122+ assert_se(r == 0);
123+
124+ r = sd_uid_get_display(u2, &display_session);
125+ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));
126+ if (u2 == UID_INVALID)
127+ assert_se(r == -EINVAL);
128+ else
129+ assert_se(IN_SET(r, 0, -ENODATA));
130+
131+ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
132+ sd_peer_get_session(pair[0], &pp);
133+ sd_peer_get_session(pair[1], &qq);
134+ assert_se(streq_ptr(pp, qq));
135+
136+ r = sd_uid_get_sessions(u2, false, &sessions);
137+ assert_se(t = strv_join(sessions, " "));
138+ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
139+ if (u2 == UID_INVALID)
140+ assert_se(r == -EINVAL);
141+ else {
142 assert_se(r >= 0);
143 assert_se(r == (int) strv_length(sessions));
144- assert_se(t = strv_join(sessions, " "));
145- strv_free(sessions);
146- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
147- free(t);
148+ }
149+ sessions = strv_free(sessions);
150+ free(t);
151
152- assert_se(r == sd_uid_get_sessions(u2, false, NULL));
153+ assert_se(r == sd_uid_get_sessions(u2, false, NULL));
154
155- r = sd_uid_get_seats(u2, false, &seats);
156+ r = sd_uid_get_seats(u2, false, &seats);
157+ assert_se(t = strv_join(seats, " "));
158+ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
159+ if (u2 == UID_INVALID)
160+ assert_se(r == -EINVAL);
161+ else {
162 assert_se(r >= 0);
163 assert_se(r == (int) strv_length(seats));
164- assert_se(t = strv_join(seats, " "));
165- strv_free(seats);
166- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
167- free(t);
168-
169- assert_se(r == sd_uid_get_seats(u2, false, NULL));
170 }
171+ seats = strv_free(seats);
172+ free(t);
173+
174+ assert_se(r == sd_uid_get_seats(u2, false, NULL));
175
176 if (session) {
177 r = sd_session_is_active(session);
178@@ -109,7 +120,7 @@ static void test_login(void) {
179 log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
180
181 r = sd_session_get_state(session, &state);
182- assert_se(r >= 0);
183+ assert_se(r == 0);
184 log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
185
186 assert_se(sd_session_get_uid(session, &u) >= 0);
187@@ -123,16 +134,16 @@ static void test_login(void) {
188 log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
189
190 r = sd_session_get_display(session, &display);
191- assert_se(r >= 0 || r == -ENODATA);
192+ assert_se(IN_SET(r, 0, -ENODATA));
193 log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
194
195 r = sd_session_get_remote_user(session, &remote_user);
196- assert_se(r >= 0 || r == -ENODATA);
197+ assert_se(IN_SET(r, 0, -ENODATA));
198 log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
199 session, strna(remote_user));
200
201 r = sd_session_get_remote_host(session, &remote_host);
202- assert_se(r >= 0 || r == -ENODATA);
203+ assert_se(IN_SET(r, 0, -ENODATA));
204 log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
205 session, strna(remote_host));
206
207@@ -161,7 +172,7 @@ static void test_login(void) {
208 assert_se(r == -ENODATA);
209 }
210
211- assert_se(sd_uid_get_state(u, &state2) >= 0);
212+ assert_se(sd_uid_get_state(u, &state2) == 0);
213 log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
214 }
215
216@@ -173,11 +184,11 @@ static void test_login(void) {
217 assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
218
219 r = sd_seat_get_active(seat, &session2, &u2);
220- assert_se(r >= 0);
221+ assert_se(r == 0);
222 log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2);
223
224 r = sd_uid_is_on_seat(u, 1, seat);
225- assert_se(r >= 0);
226+ assert_se(IN_SET(r, 0, 1));
227 assert_se(!!r == streq(session, session2));
228
229 r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
230@@ -185,8 +196,8 @@ static void test_login(void) {
231 assert_se(r == (int) strv_length(sessions));
232 assert_se(t = strv_join(sessions, " "));
233 strv_free(sessions);
234- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}",
235- seat, r, t, n, format_uids(&buf, uids, n));
236+ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}",
237+ seat, e(r), t, n, format_uids(&buf, uids, n));
238 free(t);
239
240 assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
241@@ -204,7 +215,7 @@ static void test_login(void) {
242
243 r = sd_seat_get_active(NULL, &t, NULL);
244 assert_se(IN_SET(r, 0, -ENODATA));
245- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t));
246+ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t));
247 free(t);
248
249 r = sd_get_sessions(&sessions);
250@@ -244,13 +255,11 @@ static void test_login(void) {
251
252 static void test_monitor(void) {
253 sd_login_monitor *m = NULL;
254- unsigned n;
255 int r;
256
257- r = sd_login_monitor_new("session", &m);
258- assert_se(r >= 0);
259+ assert_se(sd_login_monitor_new("session", &m) == 0);
260
261- for (n = 0; n < 5; n++) {
262+ for (unsigned n = 0; n < 5; n++) {
263 struct pollfd pollfd = {};
264 usec_t timeout, nw;
diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch
new file mode 100644
index 0000000000..f02f62b772
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-3.patch
@@ -0,0 +1,182 @@
1From 0a42426d797406b4b01a0d9c13bb759c2629d108 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Wed, 7 Oct 2020 11:15:05 +0200
4Subject: [PATCH] pager: make pager secure when under euid is changed or
5 explicitly requested
6
7The variable is renamed to SYSTEMD_PAGERSECURE (because it's not just about
8less now), and we automatically enable secure mode in certain cases, but not
9otherwise.
10
11This approach is more nuanced, but should provide a better experience for
12users:
13
14- Previusly we would set LESSSECURE=1 and trust the pager to make use of
15 it. But this has an effect only on less. We need to not start pagers which
16 are insecure when in secure mode. In particular more is like that and is a
17 very popular pager.
18
19- We don't enable secure mode always, which means that those other pagers can
20 reasonably used.
21
22- We do the right thing by default, but the user has ultimate control by
23 setting SYSTEMD_PAGERSECURE.
24
25Fixes #5666.
26
27v2:
28- also check $PKEXEC_UID
29
30v3:
31- use 'sd_pid_get_owner_uid() != geteuid()' as the condition
32
33CVE: CVE-2023-26604
34Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17270/commits/0a42426d797406b4b01a0d9c13bb759c2629d108]
35Comments: Hunk refreshed
36Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
37---
38 man/less-variables.xml | 30 +++++++++++++++----
39 src/shared/pager.c | 63 ++++++++++++++++++++++++++-------------
40 2 files changed, 66 insertions(+), 27 deletions(-)
41
42diff --git a/man/less-variables.xml b/man/less-variables.xml
43index c52511c..049e9f7 100644
44--- a/man/less-variables.xml
45+++ b/man/less-variables.xml
46@@ -65,12 +65,30 @@
47 </varlistentry>
48
49 <varlistentry id='lesssecure'>
50- <term><varname>$SYSTEMD_LESSSECURE</varname></term>
51-
52- <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment
53- variable when invoking the pager, which controls the "secure" mode of less (which disables commands
54- such as <literal>|</literal> which allow to easily shell out to external command lines). By default
55- less secure mode is enabled, with this setting it may be disabled.</para></listitem>
56+ <term><varname>$SYSTEMD_PAGERSECURE</varname></term>
57+
58+ <listitem><para>Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if
59+ false, disabled. If <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, secure mode is enabled
60+ if the effective UID is not the same as the owner of the login session, see <citerefentry
61+ project='man-pages'><refentrytitle>geteuid</refentrytitle><manvolnum>2</manvolnum></citerefentry> and
62+ <citerefentry><refentrytitle>sd_pid_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
63+ In secure mode, <option>LESSSECURE=1</option> will be set when invoking the pager, and the pager shall
64+ disable commands that open or create new files or start new subprocesses. When
65+ <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, pagers which are not known to implement
66+ secure mode will not be used. (Currently only
67+ <citerefentry><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> implements
68+ secure mode.)</para>
69+
70+ <para>Note: when commands are invoked with elevated privileges, for example under <citerefentry
71+ project='man-pages'><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
72+ <citerefentry
73+ project='die-net'><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>, care
74+ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the
75+ pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname>
76+ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note
77+ that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be
78+ honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completly
79+ disable the pager using <option>--no-pager</option> instead.</para></listitem>
80 </varlistentry>
81
82 <varlistentry id='colors'>
83diff --git a/src/shared/pager.c b/src/shared/pager.c
84index a3b6576..a72d9ea 100644
85--- a/src/shared/pager.c
86+++ b/src/shared/pager.c
87@@ -8,6 +8,8 @@
88 #include <sys/prctl.h>
89 #include <unistd.h>
90
91+#include "sd-login.h"
92+
93 #include "copy.h"
94 #include "env-util.h"
95 #include "fd-util.h"
96@@ -164,25 +166,42 @@ int pager_open(PagerFlags flags) {
97 }
98
99 /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out
100- * privileged stuff. */
101- r = getenv_bool("SYSTEMD_LESSSECURE");
102- if (r == 0) { /* Remove env var if off */
103- if (unsetenv("LESSSECURE") < 0) {
104- log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m");
105- _exit(EXIT_FAILURE);
106- }
107- } else {
108- /* Set env var otherwise */
109+ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the
110+ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE
111+ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we
112+ * know to be good. */
113+ int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE");
114+ bool trust_pager = use_secure_mode >= 0;
115+ if (use_secure_mode == -ENXIO) {
116+ uid_t uid;
117+
118+ r = sd_pid_get_owner_uid(0, &uid);
119 if (r < 0)
120- log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m");
121+ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m");
122
123- if (setenv("LESSSECURE", "1", 1) < 0) {
124- log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m");
125- _exit(EXIT_FAILURE);
126- }
127+ use_secure_mode = r < 0 || uid != geteuid();
128+
129+ } else if (use_secure_mode < 0) {
130+ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m");
131+ use_secure_mode = true;
132 }
133
134- if (pager_args) {
135+ /* We generally always set variables used by less, even if we end up using a different pager.
136+ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */
137+ if (use_secure_mode)
138+ r = setenv("LESSSECURE", "1", 1);
139+ else
140+ r = unsetenv("LESSSECURE");
141+ if (r < 0) {
142+ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m");
143+ _exit(EXIT_FAILURE);
144+ }
145+
146+ if (trust_pager && pager_args) { /* The pager config might be set globally, and we cannot
147+ * know if the user adjusted it to be appropriate for the
148+ * secure mode. Thus, start the pager specified through
149+ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set
150+ * as well. */
151 r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false);
152 if (r < 0) {
153 log_error_errno(r, "Failed to write pager name to socket: %m");
154@@ -194,13 +213,14 @@ int pager_open(PagerFlags flags) {
155 "Failed to execute '%s', using fallback pagers: %m", pager_args[0]);
156 }
157
158- /* Debian's alternatives command for pagers is
159- * called 'pager'. Note that we do not call
160- * sensible-pagers here, since that is just a
161- * shell script that implements a logic that
162- * is similar to this one anyway, but is
163- * Debian-specific. */
164+ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call
165+ * sensible-pagers here, since that is just a shell script that implements a logic that is
166+ * similar to this one anyway, but is Debian-specific. */
167 FOREACH_STRING(exe, "pager", "less", "more") {
168+ /* Only less implements secure mode right now. */
169+ if (use_secure_mode && !streq(exe, "less"))
170+ continue;
171+
172 r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false);
173 if (r < 0) {
174 log_error_errno(r, "Failed to write pager name to socket: %m");
175@@ -211,6 +231,7 @@ int pager_open(PagerFlags flags) {
176 "Failed to execute '%s', using next fallback pager: %m", exe);
177 }
178
179+ /* Our builtin is also very secure. */
180 r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in)") + 1, false);
181 if (r < 0) {
182 log_error_errno(r, "Failed to write pager name to socket: %m");
diff --git a/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch b/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch
new file mode 100644
index 0000000000..bc6b0a91c2
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/CVE-2023-26604-4.patch
@@ -0,0 +1,32 @@
1From b8f736b30e20a2b44e7c34bb4e43b0d97ae77e3c Mon Sep 17 00:00:00 2001
2From: Lennart Poettering <lennart@poettering.net>
3Date: Thu, 15 Oct 2020 10:54:48 +0200
4Subject: [PATCH] pager: lets check SYSTEMD_PAGERSECURE with secure_getenv()
5
6I can't think of any real vulnerability about this, but it still feels
7better to check a variable with "secure" in its name with
8secure_getenv() rather than plain getenv().
9
10Paranoia FTW!
11
12CVE: CVE-2023-26604
13Upstream-Status: Backport [https://github.com/systemd/systemd/pull/17359/commits/b8f736b30e20a2b44e7c34bb4e43b0d97ae77e3c]
14Comments: Hunk refreshed
15Signed-off-by: rajmohan r <rajmohan.r@kpit.com>
16---
17 src/shared/pager.c | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/src/shared/pager.c b/src/shared/pager.c
21index a72d9ea..250519c 100644
22--- a/src/shared/pager.c
23+++ b/src/shared/pager.c
24@@ -170,7 +170,7 @@ int pager_open(PagerFlags flags) {
25 * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE
26 * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we
27 * know to be good. */
28- int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE");
29+ int use_secure_mode = getenv_bool_secure("SYSTEMD_PAGERSECURE");
30 bool trust_pager = use_secure_mode >= 0;
31 if (use_secure_mode == -ENXIO) {
32 uid_t uid;
diff --git a/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch
new file mode 100644
index 0000000000..86d9b0499a
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/basic-pass-allocation-info-for-ordered-set-new-and-introd.patch
@@ -0,0 +1,78 @@
1From 1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
3Date: Tue, 1 Sep 2020 12:42:35 +0200
4Subject: [PATCH] basic: pass allocation info for ordered_set_new() and
5 introduce ordered_set_ensure_put()
6
7Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/1f25c71d9d0b5fe6cf383c347dcebc2443a99fe1]
8Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
9
10---
11 src/basic/ordered-set.c | 21 +++++++++++++++++++++
12 src/basic/ordered-set.h | 18 +++++++-----------
13 2 files changed, 28 insertions(+), 11 deletions(-)
14
15diff --git a/src/basic/ordered-set.c b/src/basic/ordered-set.c
16index 7fdb47e064..fb82c17b5a 100644
17--- a/src/basic/ordered-set.c
18+++ b/src/basic/ordered-set.c
19@@ -4,6 +4,27 @@
20 #include "ordered-set.h"
21 #include "strv.h"
22
23+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) {
24+ if (*s)
25+ return 0;
26+
27+ *s = _ordered_set_new(ops HASHMAP_DEBUG_PASS_ARGS);
28+ if (!*s)
29+ return -ENOMEM;
30+
31+ return 0;
32+}
33+
34+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS) {
35+ int r;
36+
37+ r = _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_PASS_ARGS);
38+ if (r < 0)
39+ return r;
40+
41+ return ordered_set_put(*s, p);
42+}
43+
44 int ordered_set_consume(OrderedSet *s, void *p) {
45 int r;
46
47diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
48index a42a57eb49..2c241a808b 100644
49--- a/src/basic/ordered-set.h
50+++ b/src/basic/ordered-set.h
51@@ -7,20 +7,16 @@
52
53 typedef struct OrderedSet OrderedSet;
54
55-static inline OrderedSet* ordered_set_new(const struct hash_ops *ops) {
56- return (OrderedSet*) ordered_hashmap_new(ops);
57+static inline OrderedSet* _ordered_set_new(const struct hash_ops *ops HASHMAP_DEBUG_PARAMS) {
58+ return (OrderedSet*) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_PASS_ARGS);
59 }
60+#define ordered_set_new(ops) _ordered_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
61
62-static inline int ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops) {
63- if (*s)
64- return 0;
65+int _ordered_set_ensure_allocated(OrderedSet **s, const struct hash_ops *ops HASHMAP_DEBUG_PARAMS);
66+#define ordered_set_ensure_allocated(s, ops) _ordered_set_ensure_allocated(s, ops HASHMAP_DEBUG_SRC_ARGS)
67
68- *s = ordered_set_new(ops);
69- if (!*s)
70- return -ENOMEM;
71-
72- return 0;
73-}
74+int _ordered_set_ensure_put(OrderedSet **s, const struct hash_ops *ops, void *p HASHMAP_DEBUG_PARAMS);
75+#define ordered_set_ensure_put(s, hash_ops, key) _ordered_set_ensure_put(s, hash_ops, key HASHMAP_DEBUG_SRC_ARGS)
76
77 static inline OrderedSet* ordered_set_free(OrderedSet *s) {
78 return (OrderedSet*) ordered_hashmap_free((OrderedHashmap*) s);
diff --git a/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch
new file mode 100644
index 0000000000..42b6e05b55
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/introduce-ordered_set_clear-free-with-destructor.patch
@@ -0,0 +1,35 @@
1From d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5 Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 26 Apr 2021 23:52:40 +0900
4Subject: [PATCH] ordered-set: introduce
5 ordered_set_clear/free_with_destructor()
6
7Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/d38a6476aad3f2cc80a2a4bc11f3898cc06a70f5]
8Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
9
10---
11 src/basic/ordered-set.h | 11 +++++++++++
12 1 file changed, 11 insertions(+)
13
14diff --git a/src/basic/ordered-set.h b/src/basic/ordered-set.h
15index a377f20b1f..64df41766f 100644
16--- a/src/basic/ordered-set.h
17+++ b/src/basic/ordered-set.h
18@@ -63,6 +63,17 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s);
19 #define ORDERED_SET_FOREACH(e, s, i) \
20 for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
21
22+#define ordered_set_clear_with_destructor(s, f) \
23+ ({ \
24+ OrderedSet *_s = (s); \
25+ void *_item; \
26+ while ((_item = ordered_set_steal_first(_s))) \
27+ f(_item); \
28+ _s; \
29+ })
30+#define ordered_set_free_with_destructor(s, f) \
31+ ordered_set_free(ordered_set_clear_with_destructor(s, f))
32+
33 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
34 DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
35
diff --git a/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch
new file mode 100644
index 0000000000..06c523834d
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-add-skeleton-of-request-queue.patch
@@ -0,0 +1,285 @@
1From 19d9a5adf0c1a6b5a243eea0390f6f6526d569de Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Fri, 7 May 2021 15:39:16 +0900
4Subject: [PATCH] network: add skeleton of request queue
5
6This will be used in later commits.
7
8Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/19d9a5adf0c1a6b5a243eea0390f6f6526d569de]
9Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
10
11---
12 src/network/meson.build | 2 +
13 src/network/networkd-link.c | 20 +++++-
14 src/network/networkd-manager.c | 7 ++
15 src/network/networkd-manager.h | 2 +
16 src/network/networkd-queue.c | 121 +++++++++++++++++++++++++++++++++
17 src/network/networkd-queue.h | 42 ++++++++++++
18 6 files changed, 192 insertions(+), 2 deletions(-)
19 create mode 100644 src/network/networkd-queue.c
20 create mode 100644 src/network/networkd-queue.h
21
22diff --git a/src/network/meson.build b/src/network/meson.build
23index 4fca3106dc..a8b9232e64 100644
24--- a/src/network/meson.build
25+++ b/src/network/meson.build
26@@ -105,6 +105,8 @@ sources = files('''
27 networkd-network.h
28 networkd-nexthop.c
29 networkd-nexthop.h
30+ networkd-queue.c
31+ networkd-queue.h
32 networkd-route.c
33 networkd-route.h
34 networkd-routing-policy-rule.c
35diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
36index 34359b2541..2f33305a27 100644
37--- a/src/network/networkd-link.c
38+++ b/src/network/networkd-link.c
39@@ -30,6 +30,7 @@
40 #include "networkd-manager.h"
41 #include "networkd-ndisc.h"
42 #include "networkd-neighbor.h"
43+#include "networkd-queue.h"
44 #include "networkd-radv.h"
45 #include "networkd-routing-policy-rule.h"
46 #include "networkd-wifi.h"
47
48@@ -2232,6 +2244,8 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
49 if (r < 0)
50 return r;
51
52+ link_drop_requests(link);
53+
54 r = link_drop_config(link);
55 if (r < 0)
56 return r;
57@@ -2664,6 +2678,8 @@ static int link_carrier_lost(Link *link) {
58 return r;
59 }
60
61+ link_drop_requests(link);
62+
63 r = link_drop_config(link);
64 if (r < 0)
65 return r;
66diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
67index 562ce5ca54..fd576169a9 100644
68--- a/src/network/networkd-manager.c
69+++ b/src/network/networkd-manager.c
70@@ -34,6 +34,7 @@
71 #include "networkd-manager-bus.h"
72 #include "networkd-manager.h"
73 #include "networkd-network-bus.h"
74+#include "networkd-queue.h"
75 #include "networkd-speed-meter.h"
76 #include "ordered-set.h"
77 #include "path-util.h"
78@@ -406,6 +407,10 @@ int manager_new(Manager **ret) {
79 if (r < 0)
80 return r;
81
82+ r = sd_event_add_post(m->event, NULL, manager_process_requests, m);
83+ if (r < 0)
84+ return r;
85+
86 r = manager_connect_rtnl(m);
87 if (r < 0)
88 return r;
89@@ -446,6 +451,8 @@ Manager* manager_free(Manager *m) {
90
91 free(m->state_file);
92
93+ m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free);
94+
95 while ((a = hashmap_first_key(m->dhcp6_prefixes)))
96 (void) dhcp6_prefix_remove(m, a);
97 m->dhcp6_prefixes = hashmap_free(m->dhcp6_prefixes);
98diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
99index 301b97c1a1..26e8802871 100644
100--- a/src/network/networkd-manager.h
101+++ b/src/network/networkd-manager.h
102@@ -91,6 +91,8 @@ struct Manager {
103 usec_t speed_meter_usec_old;
104
105 bool dhcp4_prefix_root_cannot_set_table;
106+
107+ OrderedSet *request_queue;
108 };
109
110 int manager_new(Manager **ret);
111diff --git a/src/network/networkd-queue.c b/src/network/networkd-queue.c
112new file mode 100644
113index 0000000000..24bb2c845d
114--- /dev/null
115+++ b/src/network/networkd-queue.c
116@@ -0,0 +1,121 @@
117+/* SPDX-License-Identifier: LGPL-2.1-or-later */
118+
119+#include "networkd-address.h"
120+#include "networkd-manager.h"
121+#include "networkd-neighbor.h"
122+#include "networkd-nexthop.h"
123+#include "networkd-route.h"
124+#include "networkd-routing-policy-rule.h"
125+#include "networkd-queue.h"
126+
127+static void request_free_object(RequestType type, void *object) {
128+ switch(type) {
129+ default:
130+ assert_not_reached("invalid request type.");
131+ }
132+}
133+
134+Request *request_free(Request *req) {
135+ if (!req)
136+ return NULL;
137+
138+ if (req->on_free)
139+ req->on_free(req);
140+ if (req->consume_object)
141+ request_free_object(req->type, req->object);
142+ if (req->link && req->link->manager)
143+ ordered_set_remove(req->link->manager->request_queue, req);
144+ link_unref(req->link);
145+
146+ return mfree(req);
147+}
148+
149+DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
150+
151+void request_drop(Request *req) {
152+ if (req->message_counter)
153+ (*req->message_counter)--;
154+
155+ request_free(req);
156+}
157+
158+int link_queue_request(
159+ Link *link,
160+ RequestType type,
161+ void *object,
162+ bool consume_object,
163+ unsigned *message_counter,
164+ link_netlink_message_handler_t netlink_handler,
165+ Request **ret) {
166+
167+ _cleanup_(request_freep) Request *req = NULL;
168+ int r;
169+
170+ assert(link);
171+ assert(link->manager);
172+ assert(type >= 0 && type < _REQUEST_TYPE_MAX);
173+ assert(object);
174+ assert(netlink_handler);
175+
176+ req = new(Request, 1);
177+ if (!req) {
178+ if (consume_object)
179+ request_free_object(type, object);
180+ return -ENOMEM;
181+ }
182+
183+ *req = (Request) {
184+ .link = link,
185+ .type = type,
186+ .object = object,
187+ .consume_object = consume_object,
188+ .message_counter = message_counter,
189+ .netlink_handler = netlink_handler,
190+ };
191+
192+ link_ref(link);
193+
194+ r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req);
195+ if (r < 0)
196+ return r;
197+
198+ if (req->message_counter)
199+ (*req->message_counter)++;
200+
201+ if (ret)
202+ *ret = req;
203+
204+ TAKE_PTR(req);
205+ return 0;
206+}
207+
208+int manager_process_requests(sd_event_source *s, void *userdata) {
209+ Manager *manager = userdata;
210+ int r;
211+
212+ assert(manager);
213+
214+ for (;;) {
215+ bool processed = false;
216+ Request *req;
217+ Iterator i;
218+ ORDERED_SET_FOREACH(req, manager->request_queue, i) {
219+ switch(req->type) {
220+ default:
221+ return -EINVAL;
222+ }
223+ if (r < 0)
224+ link_enter_failed(req->link);
225+ if (r > 0) {
226+ ordered_set_remove(manager->request_queue, req);
227+ request_free(req);
228+ processed = true;
229+ }
230+ }
231+
232+ if (!processed)
233+ break;
234+ }
235+
236+ return 0;
237+}
238diff --git a/src/network/networkd-queue.h b/src/network/networkd-queue.h
239new file mode 100644
240index 0000000000..4558ae548f
241--- /dev/null
242+++ b/src/network/networkd-queue.h
243@@ -0,0 +1,42 @@
244+/* SPDX-License-Identifier: LGPL-2.1-or-later */
245+#pragma once
246+
247+#include "sd-event.h"
248+
249+#include "networkd-link.h"
250+
251+typedef struct Request Request;
252+
253+typedef int (*request_after_configure_handler_t)(Request*, void*);
254+typedef void (*request_on_free_handler_t)(Request*);
255+
256+typedef enum RequestType {
257+ _REQUEST_TYPE_MAX,
258+ _REQUEST_TYPE_INVALID = -EINVAL,
259+} RequestType;
260+
261+typedef struct Request {
262+ Link *link;
263+ RequestType type;
264+ bool consume_object;
265+ void *object;
266+ void *userdata;
267+ unsigned *message_counter;
268+ link_netlink_message_handler_t netlink_handler;
269+ request_after_configure_handler_t after_configure;
270+ request_on_free_handler_t on_free;
271+} Request;
272+
273+Request *request_free(Request *req);
274+void request_drop(Request *req);
275+
276+int link_queue_request(
277+ Link *link,
278+ RequestType type,
279+ void *object,
280+ bool consume_object,
281+ unsigned *message_counter,
282+ link_netlink_message_handler_t netlink_handler,
283+ Request **ret);
284+
285+int manager_process_requests(sd_event_source *s, void *userdata);
diff --git a/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch
new file mode 100644
index 0000000000..4c402e7e55
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-also-drop-requests-when-link-enters-linger-state.patch
@@ -0,0 +1,50 @@
1From 56001f023305ea99329e27141d6e6067596491a9 Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 17 May 2021 15:32:57 +0900
4Subject: [PATCH] network: also drop requests when link enters linger state
5
6Otherwise, if link is removed, several references to the link in remain
7exist in requests.
8
9Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/56001f023305ea99329e27141d6e6067596491a9]
10Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
11
12---
13 src/network/networkd-link.c | 24 +++++++++++++-----------
14 1 file changed, 13 insertions(+), 11 deletions(-)
15
16diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
17index 67d01ac44d..b56c232eca 100644
18--- a/src/network/networkd-link.c
19+++ b/src/network/networkd-link.c
20@@ -1771,6 +1771,18 @@ static void link_drop_from_master(Link *link, NetDev *netdev) {
21 link_unref(set_remove(master->slaves, link));
22 }
23
24+static void link_drop_requests(Link *link) {
25+ Request *req;
26+ Iterator i;
27+
28+ assert(link);
29+ assert(link->manager);
30+
31+ ORDERED_SET_FOREACH(req, link->manager->request_queue, i)
32+ if (req->link == link)
33+ request_drop(req);
34+}
35+
36 void link_drop(Link *link) {
37 if (!link)
38 return;
39@@ -1782,6 +1793,8 @@ void link_drop(Link *link) {
40 /* Drop all references from other links and manager. Note that async netlink calls may have
41 * references to the link, and they will be dropped when we receive replies. */
42
43+ link_drop_requests(link);
44+
45 link_free_carrier_maps(link);
46
47 if (link->network) {
48--
492.17.1
50
diff --git a/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch
new file mode 100644
index 0000000000..a186bb4095
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-fix-Link-reference-counter-issue.patch
@@ -0,0 +1,278 @@
1From cc2d7efc5ca09a7de4bec55e80476986839a655c Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Fri, 14 May 2021 15:58:15 +0900
4Subject: [PATCH] network: fix Link reference counter issue
5
6Previously, when link_new() fails, `link_unref()` was called, so,
7`Manager::links` may become dirty.
8This introduces `link_drop_or_unref()` and it will be called on
9failure.
10
11Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/cc2d7efc5ca09a7de4bec55e80476986839a655c]
12Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
13
14---
15 src/network/networkd-link.c | 240 ++++++++++++++++++------------------
16 1 file changed, 122 insertions(+), 118 deletions(-)
17
18diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
19index b56c232eca..d493afda4c 100644
20--- a/src/network/networkd-link.c
21+++ b/src/network/networkd-link.c
22@@ -540,109 +540,6 @@ static int link_update_flags(Link *link,
23 return 0;
24 }
25
26-static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
27- _cleanup_(link_unrefp) Link *link = NULL;
28- uint16_t type;
29- const char *ifname, *kind = NULL;
30- int r, ifindex;
31- unsigned short iftype;
32-
33- assert(manager);
34- assert(message);
35- assert(ret);
36-
37- /* check for link kind */
38- r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
39- if (r == 0) {
40- (void) sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind);
41- r = sd_netlink_message_exit_container(message);
42- if (r < 0)
43- return r;
44- }
45-
46- r = sd_netlink_message_get_type(message, &type);
47- if (r < 0)
48- return r;
49- else if (type != RTM_NEWLINK)
50- return -EINVAL;
51-
52- r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
53- if (r < 0)
54- return r;
55- else if (ifindex <= 0)
56- return -EINVAL;
57-
58- r = sd_rtnl_message_link_get_type(message, &iftype);
59- if (r < 0)
60- return r;
61-
62- r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname);
63- if (r < 0)
64- return r;
65-
66- link = new(Link, 1);
67- if (!link)
68- return -ENOMEM;
69-
70- *link = (Link) {
71- .n_ref = 1,
72- .manager = manager,
73- .state = LINK_STATE_PENDING,
74- .ifindex = ifindex,
75- .iftype = iftype,
76-
77- .n_dns = (unsigned) -1,
78- .dns_default_route = -1,
79- .llmnr = _RESOLVE_SUPPORT_INVALID,
80- .mdns = _RESOLVE_SUPPORT_INVALID,
81- .dnssec_mode = _DNSSEC_MODE_INVALID,
82- .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
83- };
84-
85- link->ifname = strdup(ifname);
86- if (!link->ifname)
87- return -ENOMEM;
88-
89- if (kind) {
90- link->kind = strdup(kind);
91- if (!link->kind)
92- return -ENOMEM;
93- }
94-
95- r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t *)&link->master_ifindex);
96- if (r < 0)
97- log_link_debug_errno(link, r, "New device has no master, continuing without");
98-
99- r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
100- if (r < 0)
101- log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
102-
103- if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
104- return -ENOMEM;
105-
106- if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
107- return -ENOMEM;
108-
109- if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
110- return -ENOMEM;
111-
112- r = hashmap_ensure_allocated(&manager->links, NULL);
113- if (r < 0)
114- return r;
115-
116- r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
117- if (r < 0)
118- return r;
119-
120- r = link_update_flags(link, message, false);
121- if (r < 0)
122- return r;
123-
124- *ret = TAKE_PTR(link);
125-
126- return 0;
127-}
128-
129 void link_ntp_settings_clear(Link *link) {
130 link->ntp = strv_free(link->ntp);
131 }
132@@ -2030,9 +1927,9 @@ static void link_drop_requests(Link *lin
133 request_drop(req);
134 }
135
136-void link_drop(Link *link) {
137+Link *link_drop(Link *link) {
138 if (!link)
139- return;
140+ return NULL;
141
142 assert(link->manager);
143
144@@ -2057,7 +1954,7 @@ void link_drop(Link *link) {
145
146 /* The following must be called at last. */
147 assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
148- link_unref(link);
149+ return link_unref(link);
150 }
151
152 static int link_joined(Link *link) {
153@@ -3295,6 +3192,112 @@ ipv4ll_address_fail:
154
155 return 0;
156 }
157+
158+static Link *link_drop_or_unref(Link *link) {
159+ if (!link)
160+ return NULL;
161+ if (!link->manager)
162+ return link_unref(link);
163+ return link_drop(link);
164+}
165+
166+DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref);
167+
168+static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
169+ _cleanup_(link_drop_or_unrefp) Link *link = NULL;
170+ uint16_t type;
171+ _cleanup_free_ char *ifname = NULL, *kind = NULL;
172+ int r, ifindex;
173+ unsigned short iftype;
174+
175+ assert(manager);
176+ assert(message);
177+ assert(ret);
178+
179+ r = sd_netlink_message_get_type(message, &type);
180+ if (r < 0)
181+ return r;
182+ else if (type != RTM_NEWLINK)
183+ return -EINVAL;
184+
185+ r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
186+ if (r < 0)
187+ return r;
188+ else if (ifindex <= 0)
189+ return -EINVAL;
190+
191+ r = sd_rtnl_message_link_get_type(message, &iftype);
192+ if (r < 0)
193+ return r;
194+
195+ r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, &ifname);
196+ if (r < 0)
197+ return r;
198+
199+ /* check for link kind */
200+ r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
201+ if (r >= 0) {
202+ (void) sd_netlink_message_read_string_strdup(message, IFLA_INFO_KIND, &kind);
203+ r = sd_netlink_message_exit_container(message);
204+ if (r < 0)
205+ return r;
206+ }
207+
208+ link = new(Link, 1);
209+ if (!link)
210+ return -ENOMEM;
211+
212+ *link = (Link) {
213+ .n_ref = 1,
214+ .state = LINK_STATE_PENDING,
215+ .ifindex = ifindex,
216+ .iftype = iftype,
217+ .ifname = TAKE_PTR(ifname),
218+ .kind = TAKE_PTR(kind),
219+
220+ .n_dns = (unsigned) -1,
221+ .dns_default_route = -1,
222+ .llmnr = _RESOLVE_SUPPORT_INVALID,
223+ .mdns = _RESOLVE_SUPPORT_INVALID,
224+ .dnssec_mode = _DNSSEC_MODE_INVALID,
225+ .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
226+ };
227+
228+ r = hashmap_ensure_allocated(&manager->links, NULL);
229+ if (r < 0)
230+ return r;
231+
232+ r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
233+ if (r < 0)
234+ return r;
235+
236+ link->manager = manager;
237+
238+ r = sd_netlink_message_read_u32(message, IFLA_MASTER, (uint32_t*) &link->master_ifindex);
239+ if (r < 0)
240+ log_link_debug_errno(link, r, "New device has no master, continuing without");
241+
242+ r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
243+ if (r < 0)
244+ log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
245+
246+ if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
247+ return -ENOMEM;
248+
249+ if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0)
250+ return -ENOMEM;
251+
252+ if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0)
253+ return -ENOMEM;
254+
255+ r = link_update_flags(link, message, false);
256+ if (r < 0)
257+ return r;
258+
259+ *ret = TAKE_PTR(link);
260+
261+ return 0;
262+}
263
264 int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
265 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
266
267--- a/src/network/networkd-link.h 2021-09-02 18:04:16.900542857 +0530
268+++ b/src/network/networkd-link.h 2021-09-02 18:18:56.776571563 +0530
269@@ -175,7 +175,7 @@ DEFINE_TRIVIAL_DESTRUCTOR(link_netlink_d
270
271 int link_get(Manager *m, int ifindex, Link **ret);
272 int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
273-void link_drop(Link *link);
274+Link *link_drop(Link *link);
275
276 int link_down(Link *link, link_netlink_message_handler_t callback);
277
278
diff --git a/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch
new file mode 100644
index 0000000000..65bdc611df
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/network-merge-link_drop-and-link_detach_from_manager.patch
@@ -0,0 +1,67 @@
1From 63130eb36dc51e4fd50716c585f98ebe456ca7cf Mon Sep 17 00:00:00 2001
2From: Yu Watanabe <watanabe.yu+github@gmail.com>
3Date: Mon, 17 May 2021 15:40:15 +0900
4Subject: [PATCH] network: merge link_drop() and link_detach_from_manager()
5
6link_detach_from_manager() is only called by link_drop(). It is not
7necessary to split such tiny function.
8
9Upstream-Status: Backport [https://github.com/systemd/systemd-stable/commit/63130eb36dc51e4fd50716c585f98ebe456ca7cf]
10Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
11
12---
13 src/network/networkd-link.c | 27 ++++++++++++---------------
14 1 file changed, 12 insertions(+), 15 deletions(-)
15
16diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
17index 9d30e16b0a..67d01ac44d 100644
18--- a/src/network/networkd-link.c
19+++ b/src/network/networkd-link.c
20@@ -2019,24 +2019,17 @@ static void link_drop_from_master(Link *link, NetDev *netdev) {
21 link_unref(set_remove(master->slaves, link));
22 }
23
24-static void link_detach_from_manager(Link *link) {
25- if (!link || !link->manager)
26- return;
27-
28- link_unref(set_remove(link->manager->links_requesting_uuid, link));
29- link_clean(link);
30-
31- /* The following must be called at last. */
32- assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
33- link_unref(link);
34-}
35-
36 void link_drop(Link *link) {
37- if (!link || link->state == LINK_STATE_LINGER)
38+ if (!link)
39 return;
40
41+ assert(link->manager);
42+
43 link_set_state(link, LINK_STATE_LINGER);
44
45+ /* Drop all references from other links and manager. Note that async netlink calls may have
46+ * references to the link, and they will be dropped when we receive replies. */
47+
48 link_free_carrier_maps(link);
49
50 if (link->network) {
51@@ -2044,10 +2037,14 @@ void link_drop(Link *link) {
52 link_drop_from_master(link, link->network->bond);
53 }
54
55- log_link_debug(link, "Link removed");
56+ link_unref(set_remove(link->manager->links_requesting_uuid, link));
57
58 (void) unlink(link->state_file);
59- link_detach_from_manager(link);
60+ link_clean(link);
61+
62+ /* The following must be called at last. */
63+ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
64+ link_unref(link);
65 }
66
67 static int link_joined(Link *link) {
diff --git a/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch b/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch
new file mode 100644
index 0000000000..b860da008c
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/rm-rf-optionally-fsync-after-removing-directory-tree.patch
@@ -0,0 +1,35 @@
1Backport of the following upstream commit:
2From bdfe7ada0d4d66e6d6e65f2822acbb1ec230f9c2 Mon Sep 17 00:00:00 2001
3From: Lennart Poettering <lennart@poettering.net>
4Date: Tue, 5 Oct 2021 10:32:56 +0200
5Subject: [PATCH] rm-rf: optionally fsync() after removing directory tree
6
7Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz]
8Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
9---
10 src/basic/rm-rf.c | 3 +++
11 src/basic/rm-rf.h | 1 +
12 2 files changed, 4 insertions(+)
13
14--- a/src/basic/rm-rf.c
15+++ b/src/basic/rm-rf.c
16@@ -161,6 +161,9 @@
17 ret = r;
18 }
19
20+ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0)
21+ ret = -errno;
22+
23 return ret;
24 }
25
26--- a/src/basic/rm-rf.h
27+++ b/src/basic/rm-rf.h
28@@ -11,6 +11,7 @@
29 REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */
30 REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */
31 REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */
32+ REMOVE_SYNCFS = 1 << 7, /* syncfs() the root of the specified directory after removing everything in it */
33 } RemoveFlags;
34
35 int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev);
diff --git a/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch b/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch
new file mode 100644
index 0000000000..f80e6433c6
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch
@@ -0,0 +1,318 @@
1Backport of the following upstream commit:
2From 96906b22417c65d70933976e0ee920c70c9113a4 Mon Sep 17 00:00:00 2001
3From: Lennart Poettering <lennart@poettering.net>
4Date: Tue, 26 Jan 2021 16:30:06 +0100
5Subject: [PATCH] rm-rf: refactor rm_rf_children(), split out body of directory
6 iteration loop
7
8This splits out rm_rf_children_inner() as body of the loop. We can use
9that to implement rm_rf_child() for deleting one specific entry in a
10directory.
11
12Upstream-Status: Backport [http://archive.ubuntu.com/ubuntu/pool/main/s/systemd/systemd_245.4-4ubuntu3.15.debian.tar.xz]
13Signed-off-by: Purushottam Choudhary <Purushottam.Choudhary@kpit.com>
14---
15 src/basic/rm-rf.c | 223 ++++++++++++++++++++++++++-------------------
16 src/basic/rm-rf.h | 3 +-
17 2 files changed, 131 insertions(+), 95 deletions(-)
18
19--- a/src/basic/rm-rf.c
20+++ b/src/basic/rm-rf.c
21@@ -19,138 +19,153 @@
22 #include "stat-util.h"
23 #include "string-util.h"
24
25+/* We treat tmpfs/ramfs + cgroupfs as non-physical file sytems. cgroupfs is similar to tmpfs in a way after
26+ * all: we can create arbitrary directory hierarchies in it, and hence can also use rm_rf() on it to remove
27+ * those again. */
28 static bool is_physical_fs(const struct statfs *sfs) {
29 return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs);
30 }
31
32-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
33+static int rm_rf_children_inner(
34+ int fd,
35+ const char *fname,
36+ int is_dir,
37+ RemoveFlags flags,
38+ const struct stat *root_dev) {
39+
40+ struct stat st;
41+ int r;
42+
43+ assert(fd >= 0);
44+ assert(fname);
45+
46+ if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
47+
48+ r = fstatat(fd, fname, &st, AT_SYMLINK_NOFOLLOW);
49+ if (r < 0)
50+ return r;
51+
52+ is_dir = S_ISDIR(st.st_mode);
53+ }
54+
55+ if (is_dir) {
56+ _cleanup_close_ int subdir_fd = -1;
57+ int q;
58+
59+ /* if root_dev is set, remove subdirectories only if device is same */
60+ if (root_dev && st.st_dev != root_dev->st_dev)
61+ return 0;
62+
63+ /* Stop at mount points */
64+ r = fd_is_mount_point(fd, fname, 0);
65+ if (r < 0)
66+ return r;
67+ if (r > 0)
68+ return 0;
69+
70+ if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
71+
72+ /* This could be a subvolume, try to remove it */
73+
74+ r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
75+ if (r < 0) {
76+ if (!IN_SET(r, -ENOTTY, -EINVAL))
77+ return r;
78+
79+ /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */
80+ } else
81+ /* It was a subvolume, done. */
82+ return 1;
83+ }
84+
85+ subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
86+ if (subdir_fd < 0)
87+ return -errno;
88+
89+ /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type
90+ * again for each directory */
91+ q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
92+
93+ r = unlinkat(fd, fname, AT_REMOVEDIR);
94+ if (r < 0)
95+ return r;
96+ if (q < 0)
97+ return q;
98+
99+ return 1;
100+
101+ } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
102+ r = unlinkat(fd, fname, 0);
103+ if (r < 0)
104+ return r;
105+
106+ return 1;
107+ }
108+
109+ return 0;
110+}
111+
112+int rm_rf_children(
113+ int fd,
114+ RemoveFlags flags,
115+ const struct stat *root_dev) {
116+
117 _cleanup_closedir_ DIR *d = NULL;
118 struct dirent *de;
119 int ret = 0, r;
120- struct statfs sfs;
121
122 assert(fd >= 0);
123
124 /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed
125- * fd, in all cases, including on failure.. */
126+ * fd, in all cases, including on failure. */
127+
128+ d = fdopendir(fd);
129+ if (!d) {
130+ safe_close(fd);
131+ return -errno;
132+ }
133
134 if (!(flags & REMOVE_PHYSICAL)) {
135+ struct statfs sfs;
136
137- r = fstatfs(fd, &sfs);
138- if (r < 0) {
139- safe_close(fd);
140+ if (fstatfs(dirfd(d), &sfs) < 0)
141 return -errno;
142 }
143
144 if (is_physical_fs(&sfs)) {
145- /* We refuse to clean physical file systems with this call,
146- * unless explicitly requested. This is extra paranoia just
147- * to be sure we never ever remove non-state data. */
148+ /* We refuse to clean physical file systems with this call, unless explicitly
149+ * requested. This is extra paranoia just to be sure we never ever remove non-state
150+ * data. */
151+
152 _cleanup_free_ char *path = NULL;
153
154 (void) fd_get_path(fd, &path);
155- log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.",
156- strna(path));
157-
158- safe_close(fd);
159- return -EPERM;
160+ return log_error_errno(SYNTHETIC_ERRNO(EPERM),
161+ "Attempted to remove disk file system under \"%s\", and we can't allow that.",
162+ strna(path));
163 }
164 }
165
166- d = fdopendir(fd);
167- if (!d) {
168- safe_close(fd);
169- return errno == ENOENT ? 0 : -errno;
170- }
171-
172 FOREACH_DIRENT_ALL(de, d, return -errno) {
173- bool is_dir;
174- struct stat st;
175+ int is_dir;
176
177 if (dot_or_dot_dot(de->d_name))
178 continue;
179
180- if (de->d_type == DT_UNKNOWN ||
181- (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) {
182- if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
183- if (ret == 0 && errno != ENOENT)
184- ret = -errno;
185- continue;
186- }
187-
188- is_dir = S_ISDIR(st.st_mode);
189- } else
190- is_dir = de->d_type == DT_DIR;
191-
192- if (is_dir) {
193- _cleanup_close_ int subdir_fd = -1;
194-
195- /* if root_dev is set, remove subdirectories only if device is same */
196- if (root_dev && st.st_dev != root_dev->st_dev)
197- continue;
198-
199- subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
200- if (subdir_fd < 0) {
201- if (ret == 0 && errno != ENOENT)
202- ret = -errno;
203- continue;
204- }
205-
206- /* Stop at mount points */
207- r = fd_is_mount_point(fd, de->d_name, 0);
208- if (r < 0) {
209- if (ret == 0 && r != -ENOENT)
210- ret = r;
211-
212- continue;
213- }
214- if (r > 0)
215- continue;
216-
217- if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
218-
219- /* This could be a subvolume, try to remove it */
220-
221- r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
222- if (r < 0) {
223- if (!IN_SET(r, -ENOTTY, -EINVAL)) {
224- if (ret == 0)
225- ret = r;
226-
227- continue;
228- }
229-
230- /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */
231- } else
232- /* It was a subvolume, continue. */
233- continue;
234- }
235-
236- /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file
237- * system type again for each directory */
238- r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev);
239- if (r < 0 && ret == 0)
240- ret = r;
241-
242- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) {
243- if (ret == 0 && errno != ENOENT)
244- ret = -errno;
245- }
246-
247- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) {
248-
249- if (unlinkat(fd, de->d_name, 0) < 0) {
250- if (ret == 0 && errno != ENOENT)
251- ret = -errno;
252- }
253- }
254+ is_dir =
255+ de->d_type == DT_UNKNOWN ? -1 :
256+ de->d_type == DT_DIR;
257+
258+ r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev);
259+ if (r < 0 && r != -ENOENT && ret == 0)
260+ ret = r;
261 }
262+
263 return ret;
264 }
265
266 int rm_rf(const char *path, RemoveFlags flags) {
267 int fd, r;
268- struct statfs s;
269
270 assert(path);
271
272@@ -195,9 +210,10 @@
273 if (FLAGS_SET(flags, REMOVE_ROOT)) {
274
275 if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) {
276+ struct statfs s;
277+
278 if (statfs(path, &s) < 0)
279 return -errno;
280-
281 if (is_physical_fs(&s))
282 return log_error_errno(SYNTHETIC_ERRNO(EPERM),
283 "Attempted to remove files from a disk file system under \"%s\", refusing.",
284@@ -225,3 +241,22 @@
285
286 return r;
287 }
288+
289+int rm_rf_child(int fd, const char *name, RemoveFlags flags) {
290+
291+ /* Removes one specific child of the specified directory */
292+
293+ if (fd < 0)
294+ return -EBADF;
295+
296+ if (!filename_is_valid(name))
297+ return -EINVAL;
298+
299+ if ((flags & (REMOVE_ROOT|REMOVE_MISSING_OK)) != 0) /* Doesn't really make sense here, we are not supposed to remove 'fd' anyway */
300+ return -EINVAL;
301+
302+ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME))
303+ return -EINVAL;
304+
305+ return rm_rf_children_inner(fd, name, -1, flags, NULL);
306+}
307--- a/src/basic/rm-rf.h
308+++ b/src/basic/rm-rf.h
309@@ -13,7 +13,8 @@
310 REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */
311 } RemoveFlags;
312
313-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev);
314+int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev);
315+int rm_rf_child(int fd, const char *name, RemoveFlags flags);
316 int rm_rf(const char *path, RemoveFlags flags);
317
318 /* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */
diff --git a/meta/recipes-core/systemd/systemd/systemd-pager.sh b/meta/recipes-core/systemd/systemd/systemd-pager.sh
new file mode 100644
index 0000000000..86e3e0ab78
--- /dev/null
+++ b/meta/recipes-core/systemd/systemd/systemd-pager.sh
@@ -0,0 +1,7 @@
1# Systemd expect a color capable pager, however the less provided
2# by busybox is not. This make many interaction with systemd pretty
3# annoying. As a workaround we disable the systemd pager if less
4# is not the GNU version.
5if ! less -V > /dev/null 2>&1 ; then
6 export SYSTEMD_PAGER=
7fi
diff --git a/meta/recipes-core/systemd/systemd_244.5.bb b/meta/recipes-core/systemd/systemd_244.5.bb
index 8c95648ca0..8b2f47b92f 100644
--- a/meta/recipes-core/systemd/systemd_244.5.bb
+++ b/meta/recipes-core/systemd/systemd_244.5.bb
@@ -18,8 +18,28 @@ SRC_URI += "file://touchscreen.rules \
18 file://00-create-volatile.conf \ 18 file://00-create-volatile.conf \
19 file://init \ 19 file://init \
20 file://99-default.preset \ 20 file://99-default.preset \
21 file://systemd-pager.sh \
21 file://0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch \ 22 file://0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch \
22 file://0003-implment-systemd-sysv-install-for-OE.patch \ 23 file://0003-implment-systemd-sysv-install-for-OE.patch \
24 file://CVE-2021-33910.patch \
25 file://CVE-2020-13529.patch \
26 file://basic-pass-allocation-info-for-ordered-set-new-and-introd.patch \
27 file://introduce-ordered_set_clear-free-with-destructor.patch \
28 file://network-add-skeleton-of-request-queue.patch \
29 file://network-merge-link_drop-and-link_detach_from_manager.patch \
30 file://network-also-drop-requests-when-link-enters-linger-state.patch \
31 file://network-fix-Link-reference-counter-issue.patch \
32 file://rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch \
33 file://rm-rf-optionally-fsync-after-removing-directory-tree.patch \
34 file://CVE-2018-21029.patch \
35 file://CVE-2021-3997-1.patch \
36 file://CVE-2021-3997-2.patch \
37 file://CVE-2021-3997-3.patch \
38 file://CVE-2022-3821.patch \
39 file://CVE-2023-26604-1.patch \
40 file://CVE-2023-26604-2.patch \
41 file://CVE-2023-26604-3.patch \
42 file://CVE-2023-26604-4.patch \
23 " 43 "
24 44
25# patches needed by musl 45# patches needed by musl
@@ -88,6 +108,7 @@ PACKAGECONFIG ??= " \
88 timesyncd \ 108 timesyncd \
89 utmp \ 109 utmp \
90 vconsole \ 110 vconsole \
111 wheel-group \
91 xz \ 112 xz \
92" 113"
93 114
@@ -148,6 +169,7 @@ PACKAGECONFIG[manpages] = "-Dman=true,-Dman=false,libxslt-native xmlto-native do
148PACKAGECONFIG[microhttpd] = "-Dmicrohttpd=true,-Dmicrohttpd=false,libmicrohttpd" 169PACKAGECONFIG[microhttpd] = "-Dmicrohttpd=true,-Dmicrohttpd=false,libmicrohttpd"
149PACKAGECONFIG[myhostname] = "-Dnss-myhostname=true,-Dnss-myhostname=false,,libnss-myhostname" 170PACKAGECONFIG[myhostname] = "-Dnss-myhostname=true,-Dnss-myhostname=false,,libnss-myhostname"
150PACKAGECONFIG[networkd] = "-Dnetworkd=true,-Dnetworkd=false" 171PACKAGECONFIG[networkd] = "-Dnetworkd=true,-Dnetworkd=false"
172PACKAGECONFIG[no-dns-fallback] = "-Ddns-servers="
151PACKAGECONFIG[nss] = "-Dnss-systemd=true,-Dnss-systemd=false" 173PACKAGECONFIG[nss] = "-Dnss-systemd=true,-Dnss-systemd=false"
152PACKAGECONFIG[nss-mymachines] = "-Dnss-mymachines=true,-Dnss-mymachines=false" 174PACKAGECONFIG[nss-mymachines] = "-Dnss-mymachines=true,-Dnss-mymachines=false"
153PACKAGECONFIG[nss-resolve] = "-Dnss-resolve=true,-Dnss-resolve=false" 175PACKAGECONFIG[nss-resolve] = "-Dnss-resolve=true,-Dnss-resolve=false"
@@ -180,6 +202,7 @@ PACKAGECONFIG[sbinmerge] = "-Dsplit-bin=false,-Dsplit-bin=true"
180PACKAGECONFIG[utmp] = "-Dutmp=true,-Dutmp=false" 202PACKAGECONFIG[utmp] = "-Dutmp=true,-Dutmp=false"
181PACKAGECONFIG[valgrind] = "-DVALGRIND=1,,valgrind" 203PACKAGECONFIG[valgrind] = "-DVALGRIND=1,,valgrind"
182PACKAGECONFIG[vconsole] = "-Dvconsole=true,-Dvconsole=false,,${PN}-vconsole-setup" 204PACKAGECONFIG[vconsole] = "-Dvconsole=true,-Dvconsole=false,,${PN}-vconsole-setup"
205PACKAGECONFIG[wheel-group] = "-Dwheel-group=true, -Dwheel-group=false"
183# Verify keymaps on locale change 206# Verify keymaps on locale change
184PACKAGECONFIG[xkbcommon] = "-Dxkbcommon=true,-Dxkbcommon=false,libxkbcommon" 207PACKAGECONFIG[xkbcommon] = "-Dxkbcommon=true,-Dxkbcommon=false,libxkbcommon"
185PACKAGECONFIG[xz] = "-Dxz=true,-Dxz=false,xz" 208PACKAGECONFIG[xz] = "-Dxz=true,-Dxz=false,xz"
@@ -197,10 +220,12 @@ rootlibexecdir = "${rootprefix}/lib"
197EXTRA_OEMESON += "-Dlink-udev-shared=false" 220EXTRA_OEMESON += "-Dlink-udev-shared=false"
198 221
199EXTRA_OEMESON += "-Dnobody-user=nobody \ 222EXTRA_OEMESON += "-Dnobody-user=nobody \
200 -Dnobody-group=nobody \ 223 -Dnobody-group=nogroup \
201 -Drootlibdir=${rootlibdir} \ 224 -Drootlibdir=${rootlibdir} \
202 -Drootprefix=${rootprefix} \ 225 -Drootprefix=${rootprefix} \
203 -Ddefault-locale=C \ 226 -Ddefault-locale=C \
227 -Dsystem-uid-max=999 \
228 -Dsystem-gid-max=999 \
204 " 229 "
205 230
206# Hardcode target binary paths to avoid using paths from sysroot 231# Hardcode target binary paths to avoid using paths from sysroot
@@ -298,6 +323,9 @@ do_install() {
298 # install default policy for presets 323 # install default policy for presets
299 # https://www.freedesktop.org/wiki/Software/systemd/Preset/#howto 324 # https://www.freedesktop.org/wiki/Software/systemd/Preset/#howto
300 install -Dm 0644 ${WORKDIR}/99-default.preset ${D}${systemd_unitdir}/system-preset/99-default.preset 325 install -Dm 0644 ${WORKDIR}/99-default.preset ${D}${systemd_unitdir}/system-preset/99-default.preset
326
327 # add a profile fragment to disable systemd pager with busybox less
328 install -Dm 0644 ${WORKDIR}/systemd-pager.sh ${D}${sysconfdir}/profile.d/systemd-pager.sh
301} 329}
302 330
303python populate_packages_prepend (){ 331python populate_packages_prepend (){
@@ -385,9 +413,9 @@ FILES_${PN}-binfmt = "${sysconfdir}/binfmt.d/ \
385 ${rootlibexecdir}/systemd/systemd-binfmt \ 413 ${rootlibexecdir}/systemd/systemd-binfmt \
386 ${systemd_unitdir}/system/proc-sys-fs-binfmt_misc.* \ 414 ${systemd_unitdir}/system/proc-sys-fs-binfmt_misc.* \
387 ${systemd_unitdir}/system/systemd-binfmt.service" 415 ${systemd_unitdir}/system/systemd-binfmt.service"
388RRECOMMENDS_${PN}-binfmt = "kernel-module-binfmt-misc" 416RRECOMMENDS_${PN}-binfmt = "${@bb.utils.contains('PACKAGECONFIG', 'binfmt', 'kernel-module-binfmt-misc', '', d)}"
389 417
390RRECOMMENDS_${PN}-vconsole-setup = "kbd kbd-consolefonts kbd-keymaps" 418RRECOMMENDS_${PN}-vconsole-setup = "${@bb.utils.contains('PACKAGECONFIG', 'vconsole', 'kbd kbd-consolefonts kbd-keymaps', '', d)}"
391 419
392 420
393FILES_${PN}-journal-gatewayd = "${rootlibexecdir}/systemd/systemd-journal-gatewayd \ 421FILES_${PN}-journal-gatewayd = "${rootlibexecdir}/systemd/systemd-journal-gatewayd \
@@ -520,6 +548,7 @@ FILES_${PN} = " ${base_bindir}/* \
520 ${sysconfdir}/dbus-1/ \ 548 ${sysconfdir}/dbus-1/ \
521 ${sysconfdir}/modules-load.d/ \ 549 ${sysconfdir}/modules-load.d/ \
522 ${sysconfdir}/pam.d/ \ 550 ${sysconfdir}/pam.d/ \
551 ${sysconfdir}/profile.d/ \
523 ${sysconfdir}/sysctl.d/ \ 552 ${sysconfdir}/sysctl.d/ \
524 ${sysconfdir}/systemd/ \ 553 ${sysconfdir}/systemd/ \
525 ${sysconfdir}/tmpfiles.d/ \ 554 ${sysconfdir}/tmpfiles.d/ \
diff --git a/meta/recipes-core/udev/eudev_3.2.9.bb b/meta/recipes-core/udev/eudev_3.2.9.bb
index f96f8cbe78..3ae91dee51 100644
--- a/meta/recipes-core/udev/eudev_3.2.9.bb
+++ b/meta/recipes-core/udev/eudev_3.2.9.bb
@@ -1,5 +1,6 @@
1SUMMARY = "eudev is a fork of systemd's udev" 1SUMMARY = "eudev is a fork of systemd's udev"
2HOMEPAGE = "https://wiki.gentoo.org/wiki/Eudev" 2HOMEPAGE = "https://wiki.gentoo.org/wiki/Eudev"
3DESCRIPTION = "eudev is Gentoo's fork of udev, systemd's device file manager for the Linux kernel. It manages device nodes in /dev and handles all user space actions when adding or removing devices."
3LICENSE = "GPLv2.0+ & LGPL-2.1+" 4LICENSE = "GPLv2.0+ & LGPL-2.1+"
4LICENSE_libudev = "LGPL-2.1+" 5LICENSE_libudev = "LGPL-2.1+"
5LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" 6LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
diff --git a/meta/recipes-core/update-rc.d/update-rc.d_0.8.bb b/meta/recipes-core/update-rc.d/update-rc.d_0.8.bb
index 75632d9434..daee5c224b 100644
--- a/meta/recipes-core/update-rc.d/update-rc.d_0.8.bb
+++ b/meta/recipes-core/update-rc.d/update-rc.d_0.8.bb
@@ -6,8 +6,8 @@ SECTION = "base"
6LICENSE = "GPLv2+" 6LICENSE = "GPLv2+"
7LIC_FILES_CHKSUM = "file://update-rc.d;beginline=5;endline=15;md5=d40a07c27f535425934bb5001f2037d9" 7LIC_FILES_CHKSUM = "file://update-rc.d;beginline=5;endline=15;md5=d40a07c27f535425934bb5001f2037d9"
8 8
9SRC_URI = "git://git.yoctoproject.org/update-rc.d" 9SRC_URI = "git://git.yoctoproject.org/update-rc.d;branch=master"
10SRCREV = "4b150b25b38de688d25cde2b2d22c268ed65a748" 10SRCREV = "8636cf478d426b568c1be11dbd9346f67e03adac"
11 11
12UPSTREAM_CHECK_COMMITS = "1" 12UPSTREAM_CHECK_COMMITS = "1"
13 13
diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc
index 0e85603d9a..7b780352be 100644
--- a/meta/recipes-core/util-linux/util-linux.inc
+++ b/meta/recipes-core/util-linux/util-linux.inc
@@ -59,12 +59,13 @@ python util_linux_binpackages () {
59 continue 59 continue
60 60
61 pkg = os.path.basename(os.readlink(file)) 61 pkg = os.path.basename(os.readlink(file))
62 extras[pkg] = extras.get(pkg, '') + ' ' + file.replace(dvar, '', 1) 62 extras.setdefault(pkg, [])
63 extras[pkg].append(file.replace(dvar, '', 1))
63 64
64 pn = d.getVar('PN') 65 pn = d.getVar('PN')
65 for pkg, links in extras.items(): 66 for pkg, links in extras.items():
66 of = d.getVar('FILES_' + pn + '-' + pkg) 67 of = d.getVar('FILES_' + pn + '-' + pkg)
67 links = of + links 68 links = of + " " + " ".join(sorted(links))
68 d.setVar('FILES_' + pn + '-' + pkg, links) 69 d.setVar('FILES_' + pn + '-' + pkg, links)
69} 70}
70 71
@@ -94,7 +95,7 @@ EXTRA_OECONF = "\
94 \ 95 \
95 --disable-bfs --disable-chfn-chsh --disable-login \ 96 --disable-bfs --disable-chfn-chsh --disable-login \
96 --disable-makeinstall-chown --disable-minix --disable-newgrp \ 97 --disable-makeinstall-chown --disable-minix --disable-newgrp \
97 --disable-use-tty-group --disable-vipw \ 98 --disable-use-tty-group --disable-vipw --disable-raw \
98 \ 99 \
99 --without-udev \ 100 --without-udev \
100 \ 101 \
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2021-37600.patch b/meta/recipes-core/util-linux/util-linux/CVE-2021-37600.patch
new file mode 100644
index 0000000000..2b306c435b
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2021-37600.patch
@@ -0,0 +1,33 @@
1From 1c9143d0c1f979c3daf10e1c37b5b1e916c22a1c Mon Sep 17 00:00:00 2001
2From: Karel Zak <kzak@redhat.com>
3Date: Tue, 27 Jul 2021 11:58:31 +0200
4Subject: [PATCH] sys-utils/ipcutils: be careful when call calloc() for uint64
5 nmembs
6
7Fix: https://github.com/karelzak/util-linux/issues/1395
8Signed-off-by: Karel Zak <kzak@redhat.com>
9
10CVE: CVE-2021-37600
11Upstream-Status: Backport [1c9143d0c1f979c3daf10e1c37b5b1e916c22a1c]
12
13Signed-off-by: Dragos-Marian Panait <dragos.panait@windriver.com>
14---
15 sys-utils/ipcutils.c | 2 +-
16 1 file changed, 1 insertion(+), 1 deletion(-)
17
18diff --git a/sys-utils/ipcutils.c b/sys-utils/ipcutils.c
19index e784c4dcb..18868cfd3 100644
20--- a/sys-utils/ipcutils.c
21+++ b/sys-utils/ipcutils.c
22@@ -218,7 +218,7 @@ static void get_sem_elements(struct sem_data *p)
23 {
24 size_t i;
25
26- if (!p || !p->sem_nsems || p->sem_perm.id < 0)
27+ if (!p || !p->sem_nsems || p->sem_nsems > SIZE_MAX || p->sem_perm.id < 0)
28 return;
29
30 p->elements = xcalloc(p->sem_nsems, sizeof(struct sem_elem));
31--
322.25.1
33
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2021-3995.patch b/meta/recipes-core/util-linux/util-linux/CVE-2021-3995.patch
new file mode 100644
index 0000000000..1dcb66ad1d
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2021-3995.patch
@@ -0,0 +1,139 @@
1From f3db9bd609494099f0c1b95231c5dfe383346929 Mon Sep 17 00:00:00 2001
2From: Karel Zak <kzak@redhat.com>
3Date: Wed, 24 Nov 2021 13:53:25 +0100
4Subject: [PATCH] libmount: fix UID check for FUSE umount [CVE-2021-3995]
5
6Improper UID check allows an unprivileged user to unmount FUSE
7filesystems of users with similar UID.
8
9Signed-off-by: Karel Zak <kzak@redhat.com>
10
11CVE: CVE-2021-3995
12Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/f3db9bd609494099f0c1b95231c5dfe383346929]
13Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
14
15---
16 include/strutils.h | 2 +-
17 libmount/src/context_umount.c | 14 +++---------
18 libmount/src/mountP.h | 1 +
19 libmount/src/optstr.c | 42 +++++++++++++++++++++++++++++++++++
20 4 files changed, 47 insertions(+), 12 deletions(-)
21
22diff --git a/include/strutils.h b/include/strutils.h
23index 6e95707ea9..a84d29594d 100644
24--- a/include/strutils.h
25+++ b/include/strutils.h
26@@ -91,8 +91,8 @@ static inline char *mem2strcpy(char *dest, const void *src, size_t n, size_t nma
27 if (n + 1 > nmax)
28 n = nmax - 1;
29
30+ memset(dest, '\0', nmax);
31 memcpy(dest, src, n);
32- dest[nmax-1] = '\0';
33 return dest;
34 }
35
36diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c
37index 173637a15a..8773c65ffa 100644
38--- a/libmount/src/context_umount.c
39+++ b/libmount/src/context_umount.c
40@@ -393,10 +393,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
41 struct libmnt_ns *ns_old;
42 const char *type = mnt_fs_get_fstype(cxt->fs);
43 const char *optstr;
44- char *user_id = NULL;
45- size_t sz;
46- uid_t uid;
47- char uidstr[sizeof(stringify_value(ULONG_MAX))];
48+ uid_t uid, entry_uid;
49
50 *errsv = 0;
51
52@@ -413,11 +410,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
53 optstr = mnt_fs_get_fs_options(cxt->fs);
54 if (!optstr)
55 return 0;
56-
57- if (mnt_optstr_get_option(optstr, "user_id", &user_id, &sz) != 0)
58- return 0;
59-
60- if (sz == 0 || user_id == NULL)
61+ if (mnt_optstr_get_uid(optstr, "user_id", &entry_uid) != 0)
62 return 0;
63
64 /* get current user */
65@@ -434,8 +427,7 @@ static int is_fuse_usermount(struct libmnt_context *cxt, int *errsv)
66 return 0;
67 }
68
69- snprintf(uidstr, sizeof(uidstr), "%lu", (unsigned long) uid);
70- return strncmp(user_id, uidstr, sz) == 0;
71+ return uid == entry_uid;
72 }
73
74 /*
75diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
76index d43a835418..22442ec55e 100644
77--- a/libmount/src/mountP.h
78+++ b/libmount/src/mountP.h
79@@ -400,6 +400,7 @@ extern const struct libmnt_optmap *mnt_optmap_get_entry(
80 const struct libmnt_optmap **mapent);
81
82 /* optstr.c */
83+extern int mnt_optstr_get_uid(const char *optstr, const char *name, uid_t *uid);
84 extern int mnt_optstr_remove_option_at(char **optstr, char *begin, char *end);
85 extern int mnt_optstr_fix_gid(char **optstr, char *value, size_t valsz, char **next);
86 extern int mnt_optstr_fix_uid(char **optstr, char *value, size_t valsz, char **next);
87diff --git a/libmount/src/optstr.c b/libmount/src/optstr.c
88index 921b9318e7..16800f571c 100644
89--- a/libmount/src/optstr.c
90+++ b/libmount/src/optstr.c
91@@ -1090,6 +1090,48 @@ int mnt_optstr_fix_user(char **optstr)
92 return rc;
93 }
94
95+/*
96+ * Converts value from @optstr addressed by @name to uid.
97+ *
98+ * Returns: 0 on success, 1 if not found, <0 on error
99+ */
100+int mnt_optstr_get_uid(const char *optstr, const char *name, uid_t *uid)
101+{
102+ char *value = NULL;
103+ size_t valsz = 0;
104+ char buf[sizeof(stringify_value(UINT64_MAX))];
105+ int rc;
106+ uint64_t num;
107+
108+ assert(optstr);
109+ assert(name);
110+ assert(uid);
111+
112+ rc = mnt_optstr_get_option(optstr, name, &value, &valsz);
113+ if (rc != 0)
114+ goto fail;
115+
116+ if (valsz > sizeof(buf) - 1) {
117+ rc = -ERANGE;
118+ goto fail;
119+ }
120+ mem2strcpy(buf, value, valsz, sizeof(buf));
121+
122+ rc = ul_strtou64(buf, &num, 10);
123+ if (rc != 0)
124+ goto fail;
125+ if (num > ULONG_MAX || (uid_t) num != num) {
126+ rc = -ERANGE;
127+ goto fail;
128+ }
129+ *uid = (uid_t) num;
130+
131+ return 0;
132+fail:
133+ DBG(UTILS, ul_debug("failed to convert '%s'= to number [rc=%d]", name, rc));
134+ return rc;
135+}
136+
137 /**
138 * mnt_match_options:
139 * @optstr: options string
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2021-3996.patch b/meta/recipes-core/util-linux/util-linux/CVE-2021-3996.patch
new file mode 100644
index 0000000000..1610b5a0fe
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2021-3996.patch
@@ -0,0 +1,226 @@
1From 018a10907fa9885093f6d87401556932c2d8bd2b Mon Sep 17 00:00:00 2001
2From: Karel Zak <kzak@redhat.com>
3Date: Tue, 4 Jan 2022 10:54:20 +0100
4Subject: [PATCH] libmount: fix (deleted) suffix issue [CVE-2021-3996]
5
6This issue is related to parsing the /proc/self/mountinfo file allows an
7unprivileged user to unmount other user's filesystems that are either
8world-writable themselves or mounted in a world-writable directory.
9
10The support for "(deleted)" is no more necessary as the Linux kernel does
11not use it in /proc/self/mountinfo and /proc/self/mount files anymore.
12
13Signed-off-by: Karel Zak <kzak@redhat.com>
14
15CVE: CVE-2021-3996
16Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/018a10907fa9885093f6d87401556932c2d8bd2b]
17Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
18
19---
20 libmount/src/tab_parse.c | 5 -----
21 tests/expected/findmnt/filter-options | 1 -
22 tests/expected/findmnt/filter-options-nameval-neg | 3 +--
23 tests/expected/findmnt/filter-types-neg | 1 -
24 tests/expected/findmnt/outputs-default | 3 +--
25 tests/expected/findmnt/outputs-force-tree | 3 +--
26 tests/expected/findmnt/outputs-kernel | 3 +--
27 tests/expected/libmount/tabdiff-mount | 1 -
28 tests/expected/libmount/tabdiff-move | 1 -
29 tests/expected/libmount/tabdiff-remount | 1 -
30 tests/expected/libmount/tabdiff-umount | 1 -
31 tests/expected/libmount/tabfiles-parse-mountinfo | 11 -----------
32 tests/expected/libmount/tabfiles-py-parse-mountinfo | 11 -----------
33 tests/ts/findmnt/files/mountinfo | 1 -
34 tests/ts/findmnt/files/mountinfo-nonroot | 1 -
35 tests/ts/libmount/files/mountinfo | 1 -
36 16 files changed, 4 insertions(+), 44 deletions(-)
37
38diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c
39index 917779ab6d..4407f9c9c7 100644
40--- a/libmount/src/tab_parse.c
41+++ b/libmount/src/tab_parse.c
42@@ -225,11 +225,6 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, const char *s)
43 goto fail;
44 }
45
46- /* remove "\040(deleted)" suffix */
47- p = (char *) endswith(fs->target, PATH_DELETED_SUFFIX);
48- if (p && *p)
49- *p = '\0';
50-
51 s = skip_separator(s);
52
53 /* (6) vfs options (fs-independent) */
54diff --git a/tests/expected/findmnt/filter-options b/tests/expected/findmnt/filter-options
55index 2606bce76b..97b0ead0ad 100644
56--- a/tests/expected/findmnt/filter-options
57+++ b/tests/expected/findmnt/filter-options
58@@ -28,5 +28,4 @@ TARGET SOURCE FSTYPE OPTIONS
59 /home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
60 /var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
61 /mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
62-/mnt/foo /fooooo bar rw,relatime
63 rc=0
64diff --git a/tests/expected/findmnt/filter-options-nameval-neg b/tests/expected/findmnt/filter-options-nameval-neg
65index 5471d65af1..f0467ef755 100644
66--- a/tests/expected/findmnt/filter-options-nameval-neg
67+++ b/tests/expected/findmnt/filter-options-nameval-neg
68@@ -29,6 +29,5 @@ TARGET SOURCE FSTYPE OPTIO
69 |-/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered
70 | `-/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
71 |-/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
72-|-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
73-`-/mnt/foo /fooooo bar rw,relatime
74+`-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
75 rc=0
76diff --git a/tests/expected/findmnt/filter-types-neg b/tests/expected/findmnt/filter-types-neg
77index 2606bce76b..97b0ead0ad 100644
78--- a/tests/expected/findmnt/filter-types-neg
79+++ b/tests/expected/findmnt/filter-types-neg
80@@ -28,5 +28,4 @@ TARGET SOURCE FSTYPE OPTIONS
81 /home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
82 /var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
83 /mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
84-/mnt/foo /fooooo bar rw,relatime
85 rc=0
86diff --git a/tests/expected/findmnt/outputs-default b/tests/expected/findmnt/outputs-default
87index 59495797bd..01599355ec 100644
88--- a/tests/expected/findmnt/outputs-default
89+++ b/tests/expected/findmnt/outputs-default
90@@ -30,6 +30,5 @@ TARGET SOURCE FSTYPE OPTIO
91 |-/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered
92 | `-/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
93 |-/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
94-|-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
95-`-/mnt/foo /fooooo bar rw,relatime
96+`-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
97 rc=0
98diff --git a/tests/expected/findmnt/outputs-force-tree b/tests/expected/findmnt/outputs-force-tree
99index 59495797bd..01599355ec 100644
100--- a/tests/expected/findmnt/outputs-force-tree
101+++ b/tests/expected/findmnt/outputs-force-tree
102@@ -30,6 +30,5 @@ TARGET SOURCE FSTYPE OPTIO
103 |-/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered
104 | `-/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
105 |-/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
106-|-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
107-`-/mnt/foo /fooooo bar rw,relatime
108+`-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
109 rc=0
110diff --git a/tests/expected/findmnt/outputs-kernel b/tests/expected/findmnt/outputs-kernel
111index 59495797bd..01599355ec 100644
112--- a/tests/expected/findmnt/outputs-kernel
113+++ b/tests/expected/findmnt/outputs-kernel
114@@ -30,6 +30,5 @@ TARGET SOURCE FSTYPE OPTIO
115 |-/home/kzak /dev/mapper/kzak-home ext4 rw,noatime,barrier=1,data=ordered
116 | `-/home/kzak/.gvfs gvfs-fuse-daemon fuse.gvfs-fuse-daemon rw,nosuid,nodev,relatime,user_id=500,group_id=500
117 |-/var/lib/nfs/rpc_pipefs sunrpc rpc_pipefs rw,relatime
118-|-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
119-`-/mnt/foo /fooooo bar rw,relatime
120+`-/mnt/sounds //foo.home/bar/ cifs rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
121 rc=0
122diff --git a/tests/expected/libmount/tabdiff-mount b/tests/expected/libmount/tabdiff-mount
123index 420aeacd5e..3c18f8dc4f 100644
124--- a/tests/expected/libmount/tabdiff-mount
125+++ b/tests/expected/libmount/tabdiff-mount
126@@ -1,3 +1,2 @@
127 /dev/mapper/kzak-home on /home/kzak: MOUNTED
128-/fooooo on /mnt/foo: MOUNTED
129 tmpfs on /mnt/test/foo bar: MOUNTED
130diff --git a/tests/expected/libmount/tabdiff-move b/tests/expected/libmount/tabdiff-move
131index 24f9bc791b..95820d93ef 100644
132--- a/tests/expected/libmount/tabdiff-move
133+++ b/tests/expected/libmount/tabdiff-move
134@@ -1,3 +1,2 @@
135 //foo.home/bar/ on /mnt/music: MOVED to /mnt/music
136-/fooooo on /mnt/foo: UMOUNTED
137 tmpfs on /mnt/test/foo bar: UMOUNTED
138diff --git a/tests/expected/libmount/tabdiff-remount b/tests/expected/libmount/tabdiff-remount
139index 82ebeab390..876bfd9539 100644
140--- a/tests/expected/libmount/tabdiff-remount
141+++ b/tests/expected/libmount/tabdiff-remount
142@@ -1,4 +1,3 @@
143 /dev/mapper/kzak-home on /home/kzak: REMOUNTED from 'rw,noatime,barrier=1,data=ordered' to 'ro,noatime,barrier=1,data=ordered'
144 //foo.home/bar/ on /mnt/sounds: REMOUNTED from 'rw,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344' to 'ro,relatime,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344'
145-/fooooo on /mnt/foo: UMOUNTED
146 tmpfs on /mnt/test/foo bar: UMOUNTED
147diff --git a/tests/expected/libmount/tabdiff-umount b/tests/expected/libmount/tabdiff-umount
148index a3e0fe48a1..c7be725b92 100644
149--- a/tests/expected/libmount/tabdiff-umount
150+++ b/tests/expected/libmount/tabdiff-umount
151@@ -1,3 +1,2 @@
152 /dev/mapper/kzak-home on /home/kzak: UMOUNTED
153-/fooooo on /mnt/foo: UMOUNTED
154 tmpfs on /mnt/test/foo bar: UMOUNTED
155diff --git a/tests/expected/libmount/tabfiles-parse-mountinfo b/tests/expected/libmount/tabfiles-parse-mountinfo
156index 47eb770061..d5ba5248e4 100644
157--- a/tests/expected/libmount/tabfiles-parse-mountinfo
158+++ b/tests/expected/libmount/tabfiles-parse-mountinfo
159@@ -351,17 +351,6 @@ id: 47
160 parent: 20
161 devno: 0:38
162 ------ fs:
163-source: /fooooo
164-target: /mnt/foo
165-fstype: bar
166-optstr: rw,relatime
167-VFS-optstr: rw,relatime
168-FS-opstr: rw
169-root: /
170-id: 48
171-parent: 20
172-devno: 0:39
173------- fs:
174 source: tmpfs
175 target: /mnt/test/foo bar
176 fstype: tmpfs
177diff --git a/tests/expected/libmount/tabfiles-py-parse-mountinfo b/tests/expected/libmount/tabfiles-py-parse-mountinfo
178index 47eb770061..d5ba5248e4 100644
179--- a/tests/expected/libmount/tabfiles-py-parse-mountinfo
180+++ b/tests/expected/libmount/tabfiles-py-parse-mountinfo
181@@ -351,17 +351,6 @@ id: 47
182 parent: 20
183 devno: 0:38
184 ------ fs:
185-source: /fooooo
186-target: /mnt/foo
187-fstype: bar
188-optstr: rw,relatime
189-VFS-optstr: rw,relatime
190-FS-opstr: rw
191-root: /
192-id: 48
193-parent: 20
194-devno: 0:39
195------- fs:
196 source: tmpfs
197 target: /mnt/test/foo bar
198 fstype: tmpfs
199diff --git a/tests/ts/findmnt/files/mountinfo b/tests/ts/findmnt/files/mountinfo
200index 475ea1a337..ff1e664a84 100644
201--- a/tests/ts/findmnt/files/mountinfo
202+++ b/tests/ts/findmnt/files/mountinfo
203@@ -30,4 +30,3 @@
204 44 41 0:36 / /home/kzak/.gvfs rw,nosuid,nodev,relatime - fuse.gvfs-fuse-daemon gvfs-fuse-daemon rw,user_id=500,group_id=500
205 45 20 0:37 / /var/lib/nfs/rpc_pipefs rw,relatime - rpc_pipefs sunrpc rw
206 47 20 0:38 / /mnt/sounds rw,relatime - cifs //foo.home/bar/ rw,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
207-48 20 0:39 / /mnt/foo\040(deleted) rw,relatime - bar /fooooo rw
208diff --git a/tests/ts/findmnt/files/mountinfo-nonroot b/tests/ts/findmnt/files/mountinfo-nonroot
209index e15b467016..87b421d2ef 100644
210--- a/tests/ts/findmnt/files/mountinfo-nonroot
211+++ b/tests/ts/findmnt/files/mountinfo-nonroot
212@@ -29,4 +29,3 @@
213 44 41 0:36 / /home/kzak/.gvfs rw,nosuid,nodev,relatime - fuse.gvfs-fuse-daemon gvfs-fuse-daemon rw,user_id=500,group_id=500
214 45 20 0:37 / /var/lib/nfs/rpc_pipefs rw,relatime - rpc_pipefs sunrpc rw
215 47 20 0:38 / /mnt/sounds rw,relatime - cifs //foo.home/bar/ rw,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
216-48 20 0:39 / /mnt/foo\040(deleted) rw,relatime - bar /fooooo rw
217diff --git a/tests/ts/libmount/files/mountinfo b/tests/ts/libmount/files/mountinfo
218index c063071833..2b01740481 100644
219--- a/tests/ts/libmount/files/mountinfo
220+++ b/tests/ts/libmount/files/mountinfo
221@@ -30,5 +30,4 @@
222 44 41 0:36 / /home/kzak/.gvfs rw,nosuid,nodev,relatime - fuse.gvfs-fuse-daemon gvfs-fuse-daemon rw,user_id=500,group_id=500
223 45 20 0:37 / /var/lib/nfs/rpc_pipefs rw,relatime - rpc_pipefs sunrpc rw
224 47 20 0:38 / /mnt/sounds rw,relatime - cifs //foo.home/bar/ rw,unc=\\foo.home\bar,username=kzak,domain=SRGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.111.1,posixpaths,serverino,acl,rsize=16384,wsize=57344
225-48 20 0:39 / /mnt/foo\040(deleted) rw,relatime - bar /fooooo rw
226 49 20 0:56 / /mnt/test/foo bar rw,relatime shared:323 - tmpfs tmpfs rw
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2022-0563.patch b/meta/recipes-core/util-linux/util-linux/CVE-2022-0563.patch
new file mode 100644
index 0000000000..54b496ea3f
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2022-0563.patch
@@ -0,0 +1,161 @@
1From faa5a3a83ad0cb5e2c303edbfd8cd823c9d94c17 Mon Sep 17 00:00:00 2001
2From: Karel Zak <kzak@redhat.com>
3Date: Thu, 10 Feb 2022 12:03:17 +0100
4Subject: [PATCH] chsh, chfn: remove readline support [CVE-2022-0563]
5
6The readline library uses INPUTRC= environment variable to get a path
7to the library config file. When the library cannot parse the
8specified file, it prints an error message containing data from the
9file.
10
11Unfortunately, the library does not use secure_getenv() (or a similar
12concept) to avoid vulnerabilities that could occur if set-user-ID or
13set-group-ID programs.
14
15Reported-by: Rory Mackie <rory.mackie@trailofbits.com>
16Signed-off-by: Karel Zak <kzak@redhat.com>
17
18Upstream-status: Backport
19https://github.com/util-linux/util-linux/commit/faa5a3a83ad0cb5e2c303edbfd8cd823c9d94c17
20
21CVE: CVE-2022-0563
22
23Signed-off-by: Steve Sakoman <steve@sakoman.com>
24
25---
26 login-utils/Makemodule.am | 2 +-
27 login-utils/chfn.c | 16 +++------------
28 login-utils/chsh.c | 42 ++-------------------------------------
29 3 files changed, 6 insertions(+), 54 deletions(-)
30
31diff --git a/login-utils/Makemodule.am b/login-utils/Makemodule.am
32index fac5bfc..73636af 100644
33--- a/login-utils/Makemodule.am
34+++ b/login-utils/Makemodule.am
35@@ -82,7 +82,7 @@ chfn_chsh_sources = \
36 login-utils/ch-common.c
37 chfn_chsh_cflags = $(SUID_CFLAGS) $(AM_CFLAGS)
38 chfn_chsh_ldflags = $(SUID_LDFLAGS) $(AM_LDFLAGS)
39-chfn_chsh_ldadd = libcommon.la $(READLINE_LIBS)
40+chfn_chsh_ldadd = libcommon.la
41
42 if CHFN_CHSH_PASSWORD
43 chfn_chsh_ldadd += -lpam
44diff --git a/login-utils/chfn.c b/login-utils/chfn.c
45index b739555..2f8e44a 100644
46--- a/login-utils/chfn.c
47+++ b/login-utils/chfn.c
48@@ -56,11 +56,6 @@
49 # include "auth.h"
50 #endif
51
52-#ifdef HAVE_LIBREADLINE
53-# define _FUNCTION_DEF
54-# include <readline/readline.h>
55-#endif
56-
57 struct finfo {
58 char *full_name;
59 char *office;
60@@ -229,22 +224,17 @@ static char *ask_new_field(struct chfn_control *ctl, const char *question,
61 {
62 int len;
63 char *buf;
64-#ifndef HAVE_LIBREADLINE
65- size_t dummy = 0;
66-#endif
67
68 if (!def_val)
69 def_val = "";
70+
71 while (true) {
72 printf("%s [%s]: ", question, def_val);
73 __fpurge(stdin);
74-#ifdef HAVE_LIBREADLINE
75- rl_bind_key('\t', rl_insert);
76- if ((buf = readline(NULL)) == NULL)
77-#else
78+
79 if (getline(&buf, &dummy, stdin) < 0)
80-#endif
81 errx(EXIT_FAILURE, _("Aborted."));
82+
83 /* remove white spaces from string end */
84 ltrim_whitespace((unsigned char *) buf);
85 len = rtrim_whitespace((unsigned char *) buf);
86diff --git a/login-utils/chsh.c b/login-utils/chsh.c
87index a9ebec8..ee6ff87 100644
88--- a/login-utils/chsh.c
89+++ b/login-utils/chsh.c
90@@ -58,11 +58,6 @@
91 # include "auth.h"
92 #endif
93
94-#ifdef HAVE_LIBREADLINE
95-# define _FUNCTION_DEF
96-# include <readline/readline.h>
97-#endif
98-
99 struct sinfo {
100 char *username;
101 char *shell;
102@@ -121,33 +116,6 @@ static void print_shells(void)
103 endusershell();
104 }
105
106-#ifdef HAVE_LIBREADLINE
107-static char *shell_name_generator(const char *text, int state)
108-{
109- static size_t len;
110- char *s;
111-
112- if (!state) {
113- setusershell();
114- len = strlen(text);
115- }
116-
117- while ((s = getusershell())) {
118- if (strncmp(s, text, len) == 0)
119- return xstrdup(s);
120- }
121- return NULL;
122-}
123-
124-static char **shell_name_completion(const char *text,
125- int start __attribute__((__unused__)),
126- int end __attribute__((__unused__)))
127-{
128- rl_attempted_completion_over = 1;
129- return rl_completion_matches(text, shell_name_generator);
130-}
131-#endif
132-
133 /*
134 * parse_argv () --
135 * parse the command line arguments, and fill in "pinfo" with any
136@@ -198,20 +166,14 @@ static char *ask_new_shell(char *question, char *oldshell)
137 {
138 int len;
139 char *ans = NULL;
140-#ifdef HAVE_LIBREADLINE
141- rl_attempted_completion_function = shell_name_completion;
142-#else
143 size_t dummy = 0;
144-#endif
145+
146 if (!oldshell)
147 oldshell = "";
148 printf("%s [%s]\n", question, oldshell);
149-#ifdef HAVE_LIBREADLINE
150- if ((ans = readline("> ")) == NULL)
151-#else
152 if (getline(&ans, &dummy, stdin) < 0)
153-#endif
154 return NULL;
155+
156 /* remove the newline at the end of ans. */
157 ltrim_whitespace((unsigned char *) ans);
158 len = rtrim_whitespace((unsigned char *) ans);
159--
1602.25.1
161
diff --git a/meta/recipes-core/util-linux/util-linux/include-strutils-cleanup-strto-functions.patch b/meta/recipes-core/util-linux/util-linux/include-strutils-cleanup-strto-functions.patch
new file mode 100644
index 0000000000..5d5a370821
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/include-strutils-cleanup-strto-functions.patch
@@ -0,0 +1,270 @@
1From 84825b161ba5d18da4142893b9789b3fc71284d9 Mon Sep 17 00:00:00 2001
2From: Karel Zak <kzak@redhat.com>
3Date: Tue, 22 Jun 2021 14:20:42 +0200
4Subject: [PATCH] include/strutils: cleanup strto..() functions
5
6* add ul_strtos64() and ul_strtou64()
7* add simple test
8
9Addresses: https://github.com/karelzak/util-linux/issues/1358
10Signed-off-by: Karel Zak <kzak@redhat.com>
11
12Upstream-Backport: [https://github.com/util-linux/util-linux/commit/84825b161ba5d18da4142893b9789b3fc71284d9]
13Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
14
15---
16 include/strutils.h | 3 +
17 lib/strutils.c | 174 ++++++++++++++++++++++++++-------------------
18 2 files changed, 105 insertions(+), 72 deletions(-)
19
20diff --git a/include/strutils.h b/include/strutils.h
21index e75a2f0e17..389e849905 100644
22--- a/include/strutils.h
23+++ b/include/strutils.h
24@@ -19,6 +19,9 @@ extern int parse_size(const char *str, uintmax_t *res, int *power);
25 extern int strtosize(const char *str, uintmax_t *res);
26 extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
27
28+extern int ul_strtos64(const char *str, int64_t *num, int base);
29+extern int ul_strtou64(const char *str, uint64_t *num, int base);
30+
31 extern int16_t strtos16_or_err(const char *str, const char *errmesg);
32 extern uint16_t strtou16_or_err(const char *str, const char *errmesg);
33 extern uint16_t strtox16_or_err(const char *str, const char *errmesg);
34diff --git a/lib/strutils.c b/lib/strutils.c
35index ee2c835495..d9976dca70 100644
36--- a/lib/strutils.c
37+++ b/lib/strutils.c
38@@ -319,39 +319,80 @@ char *strndup(const char *s, size_t n)
39 }
40 #endif
41
42-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base);
43-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base);
44+/*
45+ * convert strings to numbers; returns <0 on error, and 0 on success
46+ */
47+int ul_strtos64(const char *str, int64_t *num, int base)
48+{
49+ char *end = NULL;
50
51-int16_t strtos16_or_err(const char *str, const char *errmesg)
52+ errno = 0;
53+ if (str == NULL || *str == '\0')
54+ return -EINVAL;
55+ *num = (int64_t) strtoimax(str, &end, base);
56+
57+ if (errno || str == end || (end && *end))
58+ return -EINVAL;
59+ return 0;
60+}
61+
62+int ul_strtou64(const char *str, uint64_t *num, int base)
63 {
64- int32_t num = strtos32_or_err(str, errmesg);
65+ char *end = NULL;
66
67- if (num < INT16_MIN || num > INT16_MAX) {
68- errno = ERANGE;
69- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
70- }
71- return num;
72+ errno = 0;
73+ if (str == NULL || *str == '\0')
74+ return -EINVAL;
75+ *num = (uint64_t) strtoumax(str, &end, base);
76+
77+ if (errno || str == end || (end && *end))
78+ return -EINVAL;
79+ return 0;
80 }
81
82-static uint16_t _strtou16_or_err(const char *str, const char *errmesg, int base)
83+/*
84+ * Covert strings to numbers and print message on error.
85+ *
86+ * Note that hex functions (strtox..()) returns unsigned numbers, if you need
87+ * something else then use ul_strtos64(s, &n, 16).
88+ */
89+int64_t strtos64_or_err(const char *str, const char *errmesg)
90 {
91- uint32_t num = _strtou32_or_err(str, errmesg, base);
92+ int64_t num = 0;
93
94- if (num > UINT16_MAX) {
95- errno = ERANGE;
96- err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
97+ if (ul_strtos64(str, &num, 10) != 0) {
98+ if (errno == ERANGE)
99+ err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
100+
101+ errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
102 }
103 return num;
104 }
105
106-uint16_t strtou16_or_err(const char *str, const char *errmesg)
107+uint64_t strtou64_or_err(const char *str, const char *errmesg)
108 {
109- return _strtou16_or_err(str, errmesg, 10);
110+ uint64_t num = 0;
111+
112+ if (ul_strtou64(str, &num, 10)) {
113+ if (errno == ERANGE)
114+ err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
115+
116+ errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
117+ }
118+ return num;
119 }
120
121-uint16_t strtox16_or_err(const char *str, const char *errmesg)
122+uint64_t strtox64_or_err(const char *str, const char *errmesg)
123 {
124- return _strtou16_or_err(str, errmesg, 16);
125+ uint64_t num = 0;
126+
127+ if (ul_strtou64(str, &num, 16)) {
128+ if (errno == ERANGE)
129+ err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
130+
131+ errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
132+ }
133+ return num;
134 }
135
136 int32_t strtos32_or_err(const char *str, const char *errmesg)
137@@ -365,9 +406,9 @@ int32_t strtos32_or_err(const char *str, const char *errmesg)
138 return num;
139 }
140
141-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
142+uint32_t strtou32_or_err(const char *str, const char *errmesg)
143 {
144- uint64_t num = _strtou64_or_err(str, errmesg, base);
145+ uint64_t num = strtou64_or_err(str, errmesg);
146
147 if (num > UINT32_MAX) {
148 errno = ERANGE;
149@@ -376,66 +417,48 @@ static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
150 return num;
151 }
152
153-uint32_t strtou32_or_err(const char *str, const char *errmesg)
154-{
155- return _strtou32_or_err(str, errmesg, 10);
156-}
157-
158 uint32_t strtox32_or_err(const char *str, const char *errmesg)
159 {
160- return _strtou32_or_err(str, errmesg, 16);
161+ uint64_t num = strtox64_or_err(str, errmesg);
162+
163+ if (num > UINT32_MAX) {
164+ errno = ERANGE;
165+ err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
166+ }
167+ return num;
168 }
169
170-int64_t strtos64_or_err(const char *str, const char *errmesg)
171+int16_t strtos16_or_err(const char *str, const char *errmesg)
172 {
173- int64_t num;
174- char *end = NULL;
175-
176- errno = 0;
177- if (str == NULL || *str == '\0')
178- goto err;
179- num = strtoimax(str, &end, 10);
180-
181- if (errno || str == end || (end && *end))
182- goto err;
183+ int64_t num = strtos64_or_err(str, errmesg);
184
185- return num;
186-err:
187- if (errno == ERANGE)
188+ if (num < INT16_MIN || num > INT16_MAX) {
189+ errno = ERANGE;
190 err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
191-
192- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
193+ }
194+ return num;
195 }
196
197-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base)
198+uint16_t strtou16_or_err(const char *str, const char *errmesg)
199 {
200- uintmax_t num;
201- char *end = NULL;
202-
203- errno = 0;
204- if (str == NULL || *str == '\0')
205- goto err;
206- num = strtoumax(str, &end, base);
207-
208- if (errno || str == end || (end && *end))
209- goto err;
210+ uint64_t num = strtou64_or_err(str, errmesg);
211
212- return num;
213-err:
214- if (errno == ERANGE)
215+ if (num > UINT16_MAX) {
216+ errno = ERANGE;
217 err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
218-
219- errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
220+ }
221+ return num;
222 }
223
224-uint64_t strtou64_or_err(const char *str, const char *errmesg)
225+uint16_t strtox16_or_err(const char *str, const char *errmesg)
226 {
227- return _strtou64_or_err(str, errmesg, 10);
228-}
229+ uint64_t num = strtox64_or_err(str, errmesg);
230
231-uint64_t strtox64_or_err(const char *str, const char *errmesg)
232-{
233- return _strtou64_or_err(str, errmesg, 16);
234+ if (num > UINT16_MAX) {
235+ errno = ERANGE;
236+ err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
237+ }
238+ return num;
239 }
240
241 double strtod_or_err(const char *str, const char *errmesg)
242@@ -1051,15 +1051,25 @@ static int test_strutils_cmp_paths(int a
243
244 int main(int argc, char *argv[])
245 {
246- if (argc == 3 && strcmp(argv[1], "--size") == 0)
247+ if (argc == 3 && strcmp(argv[1], "--size") == 0) {
248 return test_strutils_sizes(argc - 1, argv + 1);
249
250- else if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0)
251+ } else if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0) {
252 return test_strutils_cmp_paths(argc - 1, argv + 1);
253
254+ } else if (argc == 3 && strcmp(argv[1], "--str2num") == 0) {
255+ uint64_t n;
256+
257+ if (ul_strtou64(argv[2], &n, 10) == 0) {
258+ printf("'%s' --> %ju\n", argv[2], (uintmax_t) n);
259+ return EXIT_SUCCESS;
260+ }
261+ }
262+
263 else {
264 fprintf(stderr, "usage: %1$s --size <number>[suffix]\n"
265- " %1$s --cmp-paths <path> <path>\n",
266+ " %1$s --cmp-paths <path> <path>\n"
267+ " %1$s --num2num <str>\n",
268 argv[0]);
269 exit(EXIT_FAILURE);
270 }
diff --git a/meta/recipes-core/util-linux/util-linux_2.35.1.bb b/meta/recipes-core/util-linux/util-linux_2.35.1.bb
index 516b783887..89dc564ecb 100644
--- a/meta/recipes-core/util-linux/util-linux_2.35.1.bb
+++ b/meta/recipes-core/util-linux/util-linux_2.35.1.bb
@@ -11,6 +11,11 @@ SRC_URI += "file://configure-sbindir.patch \
11 file://0001-libfdisk-script-accept-sector-size-ignore-unknown-he.patch \ 11 file://0001-libfdisk-script-accept-sector-size-ignore-unknown-he.patch \
12 file://0001-kill-include-sys-types.h-before-checking-SYS_pidfd_s.patch \ 12 file://0001-kill-include-sys-types.h-before-checking-SYS_pidfd_s.patch \
13 file://0001-include-cleanup-pidfd-inckudes.patch \ 13 file://0001-include-cleanup-pidfd-inckudes.patch \
14 file://CVE-2021-37600.patch \
15 file://include-strutils-cleanup-strto-functions.patch \
16 file://CVE-2021-3995.patch \
17 file://CVE-2021-3996.patch \
18 file://CVE-2022-0563.patch \
14" 19"
15SRC_URI[md5sum] = "7f64882f631225f0295ca05080cee1bf" 20SRC_URI[md5sum] = "7f64882f631225f0295ca05080cee1bf"
16SRC_URI[sha256sum] = "d9de3edd287366cd908e77677514b9387b22bc7b88f45b83e1922c3597f1d7f9" 21SRC_URI[sha256sum] = "d9de3edd287366cd908e77677514b9387b22bc7b88f45b83e1922c3597f1d7f9"
diff --git a/meta/recipes-core/volatile-binds/files/volatile-binds.service.in b/meta/recipes-core/volatile-binds/files/volatile-binds.service.in
index b23355a714..4b34ebd12d 100644
--- a/meta/recipes-core/volatile-binds/files/volatile-binds.service.in
+++ b/meta/recipes-core/volatile-binds/files/volatile-binds.service.in
@@ -1,6 +1,6 @@
1[Unit] 1[Unit]
2Description=Bind mount volatile @where@ 2Description=Bind mount volatile @where@
3DefaultDependencies=false 3DefaultDependencies=no
4Before=local-fs.target 4Before=local-fs.target
5RequiresMountsFor=@whatparent@ @whereparent@ 5RequiresMountsFor=@whatparent@ @whereparent@
6ConditionPathIsReadWrite=@whatparent@ 6ConditionPathIsReadWrite=@whatparent@
diff --git a/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch
new file mode 100644
index 0000000000..5cb6183641
--- /dev/null
+++ b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch
@@ -0,0 +1,347 @@
1CVE: CVE-2018-25032
2Upstream-Status: Backport
3Signed-off-by: Ross Burton <ross.burton@arm.com>
4
5From 5c44459c3b28a9bd3283aaceab7c615f8020c531 Mon Sep 17 00:00:00 2001
6From: Mark Adler <madler@alumni.caltech.edu>
7Date: Tue, 17 Apr 2018 22:09:22 -0700
8Subject: [PATCH] Fix a bug that can crash deflate on some input when using
9 Z_FIXED.
10
11This bug was reported by Danilo Ramos of Eideticom, Inc. It has
12lain in wait 13 years before being found! The bug was introduced
13in zlib 1.2.2.2, with the addition of the Z_FIXED option. That
14option forces the use of fixed Huffman codes. For rare inputs with
15a large number of distant matches, the pending buffer into which
16the compressed data is written can overwrite the distance symbol
17table which it overlays. That results in corrupted output due to
18invalid distances, and can result in out-of-bound accesses,
19crashing the application.
20
21The fix here combines the distance buffer and literal/length
22buffers into a single symbol buffer. Now three bytes of pending
23buffer space are opened up for each literal or length/distance
24pair consumed, instead of the previous two bytes. This assures
25that the pending buffer cannot overwrite the symbol table, since
26the maximum fixed code compressed length/distance is 31 bits, and
27since there are four bytes of pending space for every three bytes
28of symbol space.
29---
30 deflate.c | 74 ++++++++++++++++++++++++++++++++++++++++---------------
31 deflate.h | 25 +++++++++----------
32 trees.c | 50 +++++++++++--------------------------
33 3 files changed, 79 insertions(+), 70 deletions(-)
34
35diff --git a/deflate.c b/deflate.c
36index 425babc00..19cba873a 100644
37--- a/deflate.c
38+++ b/deflate.c
39@@ -255,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
40 int wrap = 1;
41 static const char my_version[] = ZLIB_VERSION;
42
43- ushf *overlay;
44- /* We overlay pending_buf and d_buf+l_buf. This works since the average
45- * output size for (length,distance) codes is <= 24 bits.
46- */
47-
48 if (version == Z_NULL || version[0] != my_version[0] ||
49 stream_size != sizeof(z_stream)) {
50 return Z_VERSION_ERROR;
51@@ -329,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
52
53 s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
54
55- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
56- s->pending_buf = (uchf *) overlay;
57- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
58+ /* We overlay pending_buf and sym_buf. This works since the average size
59+ * for length/distance pairs over any compressed block is assured to be 31
60+ * bits or less.
61+ *
62+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
63+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
64+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
65+ * possible fixed-codes length/distance pair is then 31 bits total.
66+ *
67+ * sym_buf starts one-fourth of the way into pending_buf. So there are
68+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
69+ * in sym_buf is three bytes -- two for the distance and one for the
70+ * literal/length. As each symbol is consumed, the pointer to the next
71+ * sym_buf value to read moves forward three bytes. From that symbol, up to
72+ * 31 bits are written to pending_buf. The closest the written pending_buf
73+ * bits gets to the next sym_buf symbol to read is just before the last
74+ * code is written. At that time, 31*(n-2) bits have been written, just
75+ * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
76+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
77+ * symbols are written.) The closest the writing gets to what is unread is
78+ * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
79+ * can range from 128 to 32768.
80+ *
81+ * Therefore, at a minimum, there are 142 bits of space between what is
82+ * written and what is read in the overlain buffers, so the symbols cannot
83+ * be overwritten by the compressed data. That space is actually 139 bits,
84+ * due to the three-bit fixed-code block header.
85+ *
86+ * That covers the case where either Z_FIXED is specified, forcing fixed
87+ * codes, or when the use of fixed codes is chosen, because that choice
88+ * results in a smaller compressed block than dynamic codes. That latter
89+ * condition then assures that the above analysis also covers all dynamic
90+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
91+ * fewer bits than a fixed-code block would for the same set of symbols.
92+ * Therefore its average symbol length is assured to be less than 31. So
93+ * the compressed data for a dynamic block also cannot overwrite the
94+ * symbols from which it is being constructed.
95+ */
96+
97+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
98+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
99
100 if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
101 s->pending_buf == Z_NULL) {
102@@ -340,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
103 deflateEnd (strm);
104 return Z_MEM_ERROR;
105 }
106- s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
107- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
108+ s->sym_buf = s->pending_buf + s->lit_bufsize;
109+ s->sym_end = (s->lit_bufsize - 1) * 3;
110+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
111+ * on 16 bit machines and because stored blocks are restricted to
112+ * 64K-1 bytes.
113+ */
114
115 s->level = level;
116 s->strategy = strategy;
117@@ -552,7 +589,7 @@ int ZEXPORT deflatePrime (strm, bits, value)
118
119 if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
120 s = strm->state;
121- if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
122+ if (s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
123 return Z_BUF_ERROR;
124 do {
125 put = Buf_size - s->bi_valid;
126@@ -1113,7 +1150,6 @@ int ZEXPORT deflateCopy (dest, source)
127 #else
128 deflate_state *ds;
129 deflate_state *ss;
130- ushf *overlay;
131
132
133 if (deflateStateCheck(source) || dest == Z_NULL) {
134@@ -1133,8 +1169,7 @@ int ZEXPORT deflateCopy (dest, source)
135 ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
136 ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
137 ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
138- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
139- ds->pending_buf = (uchf *) overlay;
140+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
141
142 if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
143 ds->pending_buf == Z_NULL) {
144@@ -1148,8 +1183,7 @@ int ZEXPORT deflateCopy (dest, source)
145 zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
146
147 ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
148- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
149- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
150+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
151
152 ds->l_desc.dyn_tree = ds->dyn_ltree;
153 ds->d_desc.dyn_tree = ds->dyn_dtree;
154@@ -1925,7 +1959,7 @@ local block_state deflate_fast(s, flush)
155 FLUSH_BLOCK(s, 1);
156 return finish_done;
157 }
158- if (s->last_lit)
159+ if (s->sym_next)
160 FLUSH_BLOCK(s, 0);
161 return block_done;
162 }
163@@ -2056,7 +2090,7 @@ local block_state deflate_slow(s, flush)
164 FLUSH_BLOCK(s, 1);
165 return finish_done;
166 }
167- if (s->last_lit)
168+ if (s->sym_next)
169 FLUSH_BLOCK(s, 0);
170 return block_done;
171 }
172@@ -2131,7 +2165,7 @@ local block_state deflate_rle(s, flush)
173 FLUSH_BLOCK(s, 1);
174 return finish_done;
175 }
176- if (s->last_lit)
177+ if (s->sym_next)
178 FLUSH_BLOCK(s, 0);
179 return block_done;
180 }
181@@ -2170,7 +2204,7 @@ local block_state deflate_huff(s, flush)
182 FLUSH_BLOCK(s, 1);
183 return finish_done;
184 }
185- if (s->last_lit)
186+ if (s->sym_next)
187 FLUSH_BLOCK(s, 0);
188 return block_done;
189 }
190diff --git a/deflate.h b/deflate.h
191index 23ecdd312..d4cf1a98b 100644
192--- a/deflate.h
193+++ b/deflate.h
194@@ -217,7 +217,7 @@ typedef struct internal_state {
195 /* Depth of each subtree used as tie breaker for trees of equal frequency
196 */
197
198- uchf *l_buf; /* buffer for literals or lengths */
199+ uchf *sym_buf; /* buffer for distances and literals/lengths */
200
201 uInt lit_bufsize;
202 /* Size of match buffer for literals/lengths. There are 4 reasons for
203@@ -239,13 +239,8 @@ typedef struct internal_state {
204 * - I can't count above 4
205 */
206
207- uInt last_lit; /* running index in l_buf */
208-
209- ushf *d_buf;
210- /* Buffer for distances. To simplify the code, d_buf and l_buf have
211- * the same number of elements. To use different lengths, an extra flag
212- * array would be necessary.
213- */
214+ uInt sym_next; /* running index in sym_buf */
215+ uInt sym_end; /* symbol table full when sym_next reaches this */
216
217 ulg opt_len; /* bit length of current block with optimal trees */
218 ulg static_len; /* bit length of current block with static trees */
219@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
220
221 # define _tr_tally_lit(s, c, flush) \
222 { uch cc = (c); \
223- s->d_buf[s->last_lit] = 0; \
224- s->l_buf[s->last_lit++] = cc; \
225+ s->sym_buf[s->sym_next++] = 0; \
226+ s->sym_buf[s->sym_next++] = 0; \
227+ s->sym_buf[s->sym_next++] = cc; \
228 s->dyn_ltree[cc].Freq++; \
229- flush = (s->last_lit == s->lit_bufsize-1); \
230+ flush = (s->sym_next == s->sym_end); \
231 }
232 # define _tr_tally_dist(s, distance, length, flush) \
233 { uch len = (uch)(length); \
234 ush dist = (ush)(distance); \
235- s->d_buf[s->last_lit] = dist; \
236- s->l_buf[s->last_lit++] = len; \
237+ s->sym_buf[s->sym_next++] = dist; \
238+ s->sym_buf[s->sym_next++] = dist >> 8; \
239+ s->sym_buf[s->sym_next++] = len; \
240 dist--; \
241 s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
242 s->dyn_dtree[d_code(dist)].Freq++; \
243- flush = (s->last_lit == s->lit_bufsize-1); \
244+ flush = (s->sym_next == s->sym_end); \
245 }
246 #else
247 # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
248diff --git a/trees.c b/trees.c
249index 4f4a65011..decaeb7c3 100644
250--- a/trees.c
251+++ b/trees.c
252@@ -416,7 +416,7 @@ local void init_block(s)
253
254 s->dyn_ltree[END_BLOCK].Freq = 1;
255 s->opt_len = s->static_len = 0L;
256- s->last_lit = s->matches = 0;
257+ s->sym_next = s->matches = 0;
258 }
259
260 #define SMALLEST 1
261@@ -948,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
262
263 Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
264 opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
265- s->last_lit));
266+ s->sym_next / 3));
267
268 if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
269
270@@ -1017,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
271 unsigned dist; /* distance of matched string */
272 unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
273 {
274- s->d_buf[s->last_lit] = (ush)dist;
275- s->l_buf[s->last_lit++] = (uch)lc;
276+ s->sym_buf[s->sym_next++] = dist;
277+ s->sym_buf[s->sym_next++] = dist >> 8;
278+ s->sym_buf[s->sym_next++] = lc;
279 if (dist == 0) {
280 /* lc is the unmatched char */
281 s->dyn_ltree[lc].Freq++;
282@@ -1033,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
283 s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
284 s->dyn_dtree[d_code(dist)].Freq++;
285 }
286-
287-#ifdef TRUNCATE_BLOCK
288- /* Try to guess if it is profitable to stop the current block here */
289- if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
290- /* Compute an upper bound for the compressed length */
291- ulg out_length = (ulg)s->last_lit*8L;
292- ulg in_length = (ulg)((long)s->strstart - s->block_start);
293- int dcode;
294- for (dcode = 0; dcode < D_CODES; dcode++) {
295- out_length += (ulg)s->dyn_dtree[dcode].Freq *
296- (5L+extra_dbits[dcode]);
297- }
298- out_length >>= 3;
299- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
300- s->last_lit, in_length, out_length,
301- 100L - out_length*100L/in_length));
302- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
303- }
304-#endif
305- return (s->last_lit == s->lit_bufsize-1);
306- /* We avoid equality with lit_bufsize because of wraparound at 64K
307- * on 16 bit machines and because stored blocks are restricted to
308- * 64K-1 bytes.
309- */
310+ return (s->sym_next == s->sym_end);
311 }
312
313 /* ===========================================================================
314@@ -1069,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
315 {
316 unsigned dist; /* distance of matched string */
317 int lc; /* match length or unmatched char (if dist == 0) */
318- unsigned lx = 0; /* running index in l_buf */
319+ unsigned sx = 0; /* running index in sym_buf */
320 unsigned code; /* the code to send */
321 int extra; /* number of extra bits to send */
322
323- if (s->last_lit != 0) do {
324- dist = s->d_buf[lx];
325- lc = s->l_buf[lx++];
326+ if (s->sym_next != 0) do {
327+ dist = s->sym_buf[sx++] & 0xff;
328+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
329+ lc = s->sym_buf[sx++];
330 if (dist == 0) {
331 send_code(s, lc, ltree); /* send a literal byte */
332 Tracecv(isgraph(lc), (stderr," '%c' ", lc));
333@@ -1100,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
334 }
335 } /* literal or match pair ? */
336
337- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
338- Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
339- "pendingBuf overflow");
340+ /* Check that the overlay between pending_buf and sym_buf is ok: */
341+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
342
343- } while (lx < s->last_lit);
344+ } while (sx < s->sym_next);
345
346 send_code(s, END_BLOCK, ltree);
347 }
diff --git a/meta/recipes-core/zlib/zlib/CVE-2022-37434.patch b/meta/recipes-core/zlib/zlib/CVE-2022-37434.patch
new file mode 100644
index 0000000000..d29e6e0f1f
--- /dev/null
+++ b/meta/recipes-core/zlib/zlib/CVE-2022-37434.patch
@@ -0,0 +1,44 @@
1From 8617d83d6939754ae3a04fc2d22daa18eeea2a43 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Wed, 17 Aug 2022 10:15:57 +0530
4Subject: [PATCH] CVE-2022-37434
5
6Upstream-Status: Backport [https://github.com/madler/zlib/commit/eff308af425b67093bab25f80f1ae950166bece1 & https://github.com/madler/zlib/commit/1eb7682f845ac9e9bf9ae35bbfb3bad5dacbd91d]
7CVE: CVE-2022-37434
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9
10Fix a bug when getting a gzip header extra field with inflate().
11
12If the extra field was larger than the space the user provided with
13inflateGetHeader(), and if multiple calls of inflate() delivered
14the extra header data, then there could be a buffer overflow of the
15provided space. This commit assures that provided space is not
16exceeded.
17
18 Fix extra field processing bug that dereferences NULL state->head.
19
20The recent commit to fix a gzip header extra field processing bug
21introduced the new bug fixed here.
22---
23 inflate.c | 5 +++--
24 1 file changed, 3 insertions(+), 2 deletions(-)
25
26diff --git a/inflate.c b/inflate.c
27index ac333e8..cd01857 100644
28--- a/inflate.c
29+++ b/inflate.c
30@@ -759,8 +759,9 @@ int flush;
31 if (copy > have) copy = have;
32 if (copy) {
33 if (state->head != Z_NULL &&
34- state->head->extra != Z_NULL) {
35- len = state->head->extra_len - state->length;
36+ state->head->extra != Z_NULL &&
37+ (len = state->head->extra_len - state->length) <
38+ state->head->extra_max) {
39 zmemcpy(state->head->extra + len, next,
40 len + copy > state->head->extra_max ?
41 state->head->extra_max - len : copy);
42--
432.25.1
44
diff --git a/meta/recipes-core/zlib/zlib/CVE-2023-45853.patch b/meta/recipes-core/zlib/zlib/CVE-2023-45853.patch
new file mode 100644
index 0000000000..654579eb81
--- /dev/null
+++ b/meta/recipes-core/zlib/zlib/CVE-2023-45853.patch
@@ -0,0 +1,40 @@
1From 73331a6a0481067628f065ffe87bb1d8f787d10c Mon Sep 17 00:00:00 2001
2From: Hans Wennborg <hans@chromium.org>
3Date: Fri, 18 Aug 2023 11:05:33 +0200
4Subject: [PATCH] Reject overflows of zip header fields in minizip.
5
6This checks the lengths of the file name, extra field, and comment
7that would be put in the zip headers, and rejects them if they are
8too long. They are each limited to 65535 bytes in length by the zip
9format. This also avoids possible buffer overflows if the provided
10fields are too long.
11
12Upstream-Status: Backport from [https://github.com/madler/zlib/commit/73331a6a0481067628f065ffe87bb1d8f787d10c]
13CVE: CVE-2023-45853
14Signed-off-by: Ashish Sharma <asharma@mvista.com>
15---
16 contrib/minizip/zip.c | 11 +++++++++++
17 1 file changed, 11 insertions(+)
18
19diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c
20index 3d3d4cadd..0446109b2 100644
21--- a/contrib/minizip/zip.c
22+++ b/contrib/minizip/zip.c
23@@ -1043,6 +1043,17 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
24 return ZIP_PARAMERROR;
25 #endif
26
27+ // The filename and comment length must fit in 16 bits.
28+ if ((filename!=NULL) && (strlen(filename)>0xffff))
29+ return ZIP_PARAMERROR;
30+ if ((comment!=NULL) && (strlen(comment)>0xffff))
31+ return ZIP_PARAMERROR;
32+ // The extra field length must fit in 16 bits. If the member also requires
33+ // a Zip64 extra block, that will also need to fit within that 16-bit
34+ // length, but that will be checked for later.
35+ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
36+ return ZIP_PARAMERROR;
37+
38 zi = (zip64_internal*)file;
39
40 if (zi->in_opened_file_inzip == 1)
diff --git a/meta/recipes-core/zlib/zlib_1.2.11.bb b/meta/recipes-core/zlib/zlib_1.2.11.bb
index ef9431ae47..9355f0556e 100644
--- a/meta/recipes-core/zlib/zlib_1.2.11.bb
+++ b/meta/recipes-core/zlib/zlib_1.2.11.bb
@@ -8,7 +8,10 @@ LIC_FILES_CHKSUM = "file://zlib.h;beginline=6;endline=23;md5=5377232268e952e9ef6
8 8
9SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \ 9SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \
10 file://ldflags-tests.patch \ 10 file://ldflags-tests.patch \
11 file://CVE-2018-25032.patch \
11 file://run-ptest \ 12 file://run-ptest \
13 file://CVE-2022-37434.patch \
14 file://CVE-2023-45853.patch \
12 " 15 "
13UPSTREAM_CHECK_URI = "http://zlib.net/" 16UPSTREAM_CHECK_URI = "http://zlib.net/"
14 17
@@ -50,3 +53,6 @@ do_install_append_class-target() {
50} 53}
51 54
52BBCLASSEXTEND = "native nativesdk" 55BBCLASSEXTEND = "native nativesdk"
56
57# this CVE is for cloudflare zlib
58CVE_CHECK_WHITELIST += "CVE-2023-6992"