mirror of
https://git.yoctoproject.org/poky
synced 2026-02-21 17:09:42 +01:00
Compare commits
164 Commits
yocto-3.1.
...
yocto-3.1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbe19706ec | ||
|
|
b86bf0103c | ||
|
|
bf9eabafc2 | ||
|
|
8c297c4b42 | ||
|
|
658a3832de | ||
|
|
0b105ed7c8 | ||
|
|
25972743e6 | ||
|
|
2e5bead98f | ||
|
|
7dd1d3973e | ||
|
|
9e0ebdc95f | ||
|
|
9716962e34 | ||
|
|
fd1ba91818 | ||
|
|
2b4a973db3 | ||
|
|
45845f8056 | ||
|
|
d0120e8aec | ||
|
|
97b8007eff | ||
|
|
59f99476d8 | ||
|
|
7f8394e2b1 | ||
|
|
24fe566155 | ||
|
|
b8f1972b84 | ||
|
|
75bc08971b | ||
|
|
c86e8fe287 | ||
|
|
3afde32bfa | ||
|
|
0efbcefe73 | ||
|
|
c64835823a | ||
|
|
716693cccc | ||
|
|
8cabed090e | ||
|
|
be8b0f8178 | ||
|
|
7c678246f6 | ||
|
|
d3f1ae99a7 | ||
|
|
d843ae7d5d | ||
|
|
63909c1cc6 | ||
|
|
4553984904 | ||
|
|
1149fde2f4 | ||
|
|
cdc9522ede | ||
|
|
800272477a | ||
|
|
6fd1064e82 | ||
|
|
76fb1012eb | ||
|
|
1b7c8a3e7e | ||
|
|
38c0d384bd | ||
|
|
01cabaea04 | ||
|
|
72c7bacfd3 | ||
|
|
8a8d40420f | ||
|
|
a405e12beb | ||
|
|
be04eefcaf | ||
|
|
77214fc5d4 | ||
|
|
cd9a699320 | ||
|
|
5e9e6627ac | ||
|
|
facedadb5c | ||
|
|
e66a386604 | ||
|
|
aeac103466 | ||
|
|
9a045bde41 | ||
|
|
6ebec3f39b | ||
|
|
9f0c1bc687 | ||
|
|
1d15d166d0 | ||
|
|
5c342965c4 | ||
|
|
6f375f52f5 | ||
|
|
52250009cd | ||
|
|
6f56a14cdc | ||
|
|
f1cf9f0f12 | ||
|
|
0d5e538519 | ||
|
|
374e198436 | ||
|
|
42c52c4f24 | ||
|
|
1a3807e0ca | ||
|
|
c7ddb9b198 | ||
|
|
ffbede6d58 | ||
|
|
2f34ea89db | ||
|
|
aa99487732 | ||
|
|
8ae21cd487 | ||
|
|
5a6d2dc704 | ||
|
|
f6f3a08371 | ||
|
|
cd97a607c6 | ||
|
|
f4cb2f5d52 | ||
|
|
3ee56c9b97 | ||
|
|
eebb034b21 | ||
|
|
e4d507b93b | ||
|
|
d01194c739 | ||
|
|
ee94c92957 | ||
|
|
5a893c6e96 | ||
|
|
43ffc2a5e7 | ||
|
|
a9d6f0c153 | ||
|
|
e3ae311c5f | ||
|
|
278d77034e | ||
|
|
c0535262c8 | ||
|
|
5ee2872089 | ||
|
|
f38a69e59f | ||
|
|
b731a65e4f | ||
|
|
da06aaf910 | ||
|
|
4d9612b31c | ||
|
|
cbb7afa601 | ||
|
|
f27e86a4d7 | ||
|
|
16c91216f1 | ||
|
|
e62c723b0c | ||
|
|
fe546dca3f | ||
|
|
00722bacdd | ||
|
|
15854dc716 | ||
|
|
f980ef9fec | ||
|
|
994a224d40 | ||
|
|
d32656ac24 | ||
|
|
669079e7c0 | ||
|
|
ea9b55c858 | ||
|
|
0734868d9d | ||
|
|
007a6e2dad | ||
|
|
926eb08fe3 | ||
|
|
6d6d43248e | ||
|
|
b222a20f8f | ||
|
|
55b09cdc1c | ||
|
|
87f18a42d4 | ||
|
|
3978003135 | ||
|
|
7fc94c93bf | ||
|
|
02356ecdca | ||
|
|
0cbec779f5 | ||
|
|
a1886b3532 | ||
|
|
9e2099f2a8 | ||
|
|
c3d7af5d16 | ||
|
|
a0615a08c5 | ||
|
|
b347ccc7ce | ||
|
|
c58cd65c96 | ||
|
|
ea56bba866 | ||
|
|
1b52dc0663 | ||
|
|
b48424988a | ||
|
|
0485ee7a6b | ||
|
|
90175073f6 | ||
|
|
0121cb4bd1 | ||
|
|
2f978be9e2 | ||
|
|
471e51b18a | ||
|
|
1a6ed0befd | ||
|
|
3fdec9fd90 | ||
|
|
b1fdc92450 | ||
|
|
02cfe361d6 | ||
|
|
8ae48ddf5e | ||
|
|
9fa49f817d | ||
|
|
84c0692d57 | ||
|
|
b1f23e404c | ||
|
|
b4da5c4df4 | ||
|
|
c06bf61270 | ||
|
|
827548d7f7 | ||
|
|
c314fe22fd | ||
|
|
6351d145ba | ||
|
|
268614c13d | ||
|
|
d148690f1d | ||
|
|
bce2280258 | ||
|
|
995f3a6243 | ||
|
|
98d8fdd7ea | ||
|
|
6b17a4af6a | ||
|
|
5e47346311 | ||
|
|
d76406934a | ||
|
|
9ffd5243e9 | ||
|
|
e33ce6f1af | ||
|
|
3b52050443 | ||
|
|
959e7b1432 | ||
|
|
729e5e306f | ||
|
|
3e0bb5455b | ||
|
|
3afaf243ba | ||
|
|
00ba8af956 | ||
|
|
3c6a02f04a | ||
|
|
ebca640cbb | ||
|
|
b5f81a875d | ||
|
|
2ff427ee40 | ||
|
|
0de5f6a27a | ||
|
|
f7f7d5514c | ||
|
|
762bfb5fc5 | ||
|
|
dcc4dbf463 | ||
|
|
91feb9b975 |
24
SECURITY.md
Normal file
24
SECURITY.md
Normal file
@@ -0,0 +1,24 @@
|
||||
How to Report a Potential Vulnerability?
|
||||
========================================
|
||||
|
||||
If you would like to report a public issue (for example, one with a released
|
||||
CVE number), please report it using the
|
||||
[https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security Security Bugzilla].
|
||||
If you have a patch ready, submit it following the same procedure as any other
|
||||
patch as described in README.md.
|
||||
|
||||
If you are dealing with a not-yet released or urgent issue, please send a
|
||||
message to security AT yoctoproject DOT org, including as many details as
|
||||
possible: the layer or software module affected, the recipe and its version,
|
||||
and any example code, if available.
|
||||
|
||||
Branches maintained with security fixes
|
||||
---------------------------------------
|
||||
|
||||
See [https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS Stable release and LTS]
|
||||
for detailed info regarding the policies and maintenance of Stable branches.
|
||||
|
||||
The [https://wiki.yoctoproject.org/wiki/Releases Release page] contains a list of all
|
||||
releases of the Yocto Project. Versions in grey are no longer actively maintained with
|
||||
security patches, but well-tested patches may still be accepted for them for
|
||||
significant issues.
|
||||
24
bitbake/SECURITY.md
Normal file
24
bitbake/SECURITY.md
Normal file
@@ -0,0 +1,24 @@
|
||||
How to Report a Potential Vulnerability?
|
||||
========================================
|
||||
|
||||
If you would like to report a public issue (for example, one with a released
|
||||
CVE number), please report it using the
|
||||
[https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security Security Bugzilla].
|
||||
If you have a patch ready, submit it following the same procedure as any other
|
||||
patch as described in README.md.
|
||||
|
||||
If you are dealing with a not-yet released or urgent issue, please send a
|
||||
message to security AT yoctoproject DOT org, including as many details as
|
||||
possible: the layer or software module affected, the recipe and its version,
|
||||
and any example code, if available.
|
||||
|
||||
Branches maintained with security fixes
|
||||
---------------------------------------
|
||||
|
||||
See [https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS Stable release and LTS]
|
||||
for detailed info regarding the policies and maintenance of Stable branches.
|
||||
|
||||
The [https://wiki.yoctoproject.org/wiki/Releases Release page] contains a list of all
|
||||
releases of the Yocto Project. Versions in grey are no longer actively maintained with
|
||||
security patches, but well-tested patches may still be accepted for them for
|
||||
significant issues.
|
||||
@@ -229,9 +229,10 @@ class diskMonitor:
|
||||
freeInode = st.f_favail
|
||||
|
||||
if minInode and freeInode < minInode:
|
||||
# Some filesystems use dynamic inodes so can't run out
|
||||
# (e.g. btrfs). This is reported by the inode count being 0.
|
||||
if st.f_files == 0:
|
||||
# Some filesystems use dynamic inodes so can't run out.
|
||||
# This is reported by the inode count being 0 (btrfs) or the free
|
||||
# inode count being -1 (cephfs).
|
||||
if st.f_files == 0 or st.f_favail == -1:
|
||||
self.devDict[k][2] = None
|
||||
continue
|
||||
# Always show warning, the self.checked would always be False if the action is WARN
|
||||
|
||||
@@ -318,7 +318,8 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
else:
|
||||
sigfile = stampbase + "." + task + ".sigbasedata" + "." + self.basehash[tid]
|
||||
|
||||
bb.utils.mkdirhier(os.path.dirname(sigfile))
|
||||
with bb.utils.umask(0o002):
|
||||
bb.utils.mkdirhier(os.path.dirname(sigfile))
|
||||
|
||||
data = {}
|
||||
data['task'] = task
|
||||
|
||||
@@ -969,6 +969,17 @@ def which(path, item, direction = 0, history = False, executable=False):
|
||||
return "", hist
|
||||
return ""
|
||||
|
||||
@contextmanager
|
||||
def umask(new_mask):
|
||||
"""
|
||||
Context manager to set the umask to a specific mask, and restore it afterwards.
|
||||
"""
|
||||
current_mask = os.umask(new_mask)
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.umask(current_mask)
|
||||
|
||||
def to_boolean(string, default=None):
|
||||
if not string:
|
||||
return default
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
DISTRO : "3.1.27"
|
||||
DISTRO : "3.1.30"
|
||||
DISTRO_NAME_NO_CAP : "dunfell"
|
||||
DISTRO_NAME : "Dunfell"
|
||||
DISTRO_NAME_NO_CAP_MINUS_ONE : "zeus"
|
||||
YOCTO_DOC_VERSION : "3.1.27"
|
||||
YOCTO_DOC_VERSION : "3.1.30"
|
||||
YOCTO_DOC_VERSION_MINUS_ONE : "3.0.4"
|
||||
DISTRO_REL_TAG : "yocto-3.1.27"
|
||||
DOCCONF_VERSION : "3.1.27"
|
||||
DISTRO_REL_TAG : "yocto-3.1.30"
|
||||
DOCCONF_VERSION : "3.1.30"
|
||||
BITBAKE_SERIES : "1.46"
|
||||
POKYVERSION : "23.0.27"
|
||||
POKYVERSION : "23.0.30"
|
||||
YOCTO_POKY : "poky-&DISTRO_NAME_NO_CAP;-&POKYVERSION;"
|
||||
YOCTO_DL_URL : "https://downloads.yoctoproject.org"
|
||||
YOCTO_AB_URL : "https://autobuilder.yoctoproject.org"
|
||||
|
||||
@@ -34,19 +34,35 @@ and conceptual information in the :doc:`../overview-manual/overview-manual`.
|
||||
Supported Linux Distributions
|
||||
=============================
|
||||
|
||||
Currently, the Yocto Project is supported on the following
|
||||
distributions:
|
||||
Currently, the &DISTRO; release ("&DISTRO_NAME;") of the Yocto Project is
|
||||
supported on the following distributions:
|
||||
|
||||
- Ubuntu 16.04 (LTS)
|
||||
|
||||
- Ubuntu 20.04 (LTS)
|
||||
|
||||
- Ubuntu 22.04 (LTS)
|
||||
|
||||
- Fedora 37
|
||||
|
||||
- Debian GNU/Linux 11.x (Bullseye)
|
||||
|
||||
- AlmaLinux 8.8
|
||||
|
||||
The following distribution versions are still tested (being listed
|
||||
in :term:`SANITY_TESTED_DISTROS`), even though the organizations
|
||||
publishing them no longer make updates publicly available:
|
||||
|
||||
- Ubuntu 18.04 (LTS)
|
||||
|
||||
- OpenSUSE Leap 15.3
|
||||
|
||||
Finally, here are the distribution versions which were previously
|
||||
tested on former revisions of "&DISTRO_NAME;", but no longer are:
|
||||
|
||||
- Ubuntu 16.04 (LTS)
|
||||
|
||||
- Ubuntu 19.04
|
||||
|
||||
- Ubuntu 20.04
|
||||
|
||||
- Ubuntu 22.04
|
||||
|
||||
- Fedora 28
|
||||
|
||||
- Fedora 29
|
||||
@@ -67,20 +83,18 @@ distributions:
|
||||
|
||||
- CentOS 7.x
|
||||
|
||||
- CentOS 8.x
|
||||
|
||||
- Debian GNU/Linux 8.x (Jessie)
|
||||
|
||||
- Debian GNU/Linux 9.x (Stretch)
|
||||
|
||||
- Debian GNU/Linux 10.x (Buster)
|
||||
|
||||
- Debian GNU/Linux 11.x (Bullseye)
|
||||
|
||||
- OpenSUSE Leap 15.1
|
||||
|
||||
- OpenSUSE Leap 15.2
|
||||
|
||||
- OpenSUSE Leap 15.3
|
||||
|
||||
- AlmaLinux 8.5
|
||||
|
||||
- AlmaLinux 8.7
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DISTRO = "poky"
|
||||
DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
|
||||
DISTRO_VERSION = "3.1.27"
|
||||
DISTRO_VERSION = "3.1.30"
|
||||
DISTRO_CODENAME = "dunfell"
|
||||
SDK_VENDOR = "-pokysdk"
|
||||
SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${DATE}', 'snapshot')}"
|
||||
@@ -43,29 +43,13 @@ SANITY_TESTED_DISTROS ?= " \
|
||||
poky-2.7 \n \
|
||||
poky-3.0 \n \
|
||||
poky-3.1 \n \
|
||||
ubuntu-16.04 \n \
|
||||
ubuntu-18.04 \n \
|
||||
ubuntu-19.04 \n \
|
||||
ubuntu-20.04 \n \
|
||||
ubuntu-22.04 \n \
|
||||
fedora-30 \n \
|
||||
fedora-31 \n \
|
||||
fedora-32 \n \
|
||||
fedora-33 \n \
|
||||
fedora-34 \n \
|
||||
fedora-35 \n \
|
||||
fedora-36 \n \
|
||||
centos-7 \n \
|
||||
centos-8 \n \
|
||||
debian-8 \n \
|
||||
debian-9 \n \
|
||||
debian-10 \n \
|
||||
fedora-37 \n \
|
||||
debian-11 \n \
|
||||
opensuseleap-15.1 \n \
|
||||
opensuseleap-15.2 \n \
|
||||
opensuseleap-15.3 \n \
|
||||
almalinux-8.5 \n \
|
||||
almalinux-8.7 \n \
|
||||
almalinux-8.8 \n \
|
||||
"
|
||||
# add poky sanity bbclass
|
||||
INHERIT += "poky-sanity"
|
||||
|
||||
@@ -97,6 +97,8 @@ def generate_json_report(d, out_path, link_path):
|
||||
cve_check_merge_jsons(summary, data)
|
||||
filename = f.readline()
|
||||
|
||||
summary["package"].sort(key=lambda d: d['name'])
|
||||
|
||||
with open(out_path, "w") as f:
|
||||
json.dump(summary, f, indent=2)
|
||||
|
||||
|
||||
@@ -143,13 +143,14 @@ do_unpack[cleandirs] += " ${S} ${STAGING_KERNEL_DIR} ${B} ${STAGING_KERNEL_BUILD
|
||||
do_clean[cleandirs] += " ${S} ${STAGING_KERNEL_DIR} ${B} ${STAGING_KERNEL_BUILDDIR}"
|
||||
python do_symlink_kernsrc () {
|
||||
s = d.getVar("S")
|
||||
if s[-1] == '/':
|
||||
# drop trailing slash, so that os.symlink(kernsrc, s) doesn't use s as directory name and fail
|
||||
s=s[:-1]
|
||||
kernsrc = d.getVar("STAGING_KERNEL_DIR")
|
||||
if s != kernsrc:
|
||||
bb.utils.mkdirhier(kernsrc)
|
||||
bb.utils.remove(kernsrc, recurse=True)
|
||||
if s[-1] == '/':
|
||||
# drop trailing slash, so that os.symlink(kernsrc, s) doesn't use s as
|
||||
# directory name and fail
|
||||
s = s[:-1]
|
||||
if d.getVar("EXTERNALSRC"):
|
||||
# With EXTERNALSRC S will not be wiped so we can symlink to it
|
||||
os.symlink(s, kernsrc)
|
||||
@@ -404,8 +405,8 @@ kernel_do_install() {
|
||||
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS MACHINE
|
||||
if (grep -q -i -e '^CONFIG_MODULES=y$' .config); then
|
||||
oe_runmake DEPMOD=echo MODLIB=${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION} INSTALL_FW_PATH=${D}${nonarch_base_libdir}/firmware modules_install
|
||||
rm "${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/build"
|
||||
rm "${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/source"
|
||||
rm -f "${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/build"
|
||||
rm -f "${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/source"
|
||||
# If the kernel/ directory is empty remove it to prevent QA issues
|
||||
rmdir --ignore-fail-on-non-empty "${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel"
|
||||
else
|
||||
@@ -417,12 +418,26 @@ kernel_do_install() {
|
||||
#
|
||||
install -d ${D}/${KERNEL_IMAGEDEST}
|
||||
install -d ${D}/boot
|
||||
|
||||
#
|
||||
# When including an initramfs bundle inside a FIT image, the fitImage is created after the install task
|
||||
# by do_assemble_fitimage_initramfs.
|
||||
# This happens after the generation of the initramfs bundle (done by do_bundle_initramfs).
|
||||
# So, at the level of the install task we should not try to install the fitImage. fitImage is still not
|
||||
# generated yet.
|
||||
# After the generation of the fitImage, the deploy task copies the fitImage from the build directory to
|
||||
# the deploy folder.
|
||||
#
|
||||
|
||||
for imageType in ${KERNEL_IMAGETYPES} ; do
|
||||
install -m 0644 ${KERNEL_OUTPUT_DIR}/${imageType} ${D}/${KERNEL_IMAGEDEST}/${imageType}-${KERNEL_VERSION}
|
||||
if [ "${KERNEL_PACKAGE_NAME}" = "kernel" ]; then
|
||||
ln -sf ${imageType}-${KERNEL_VERSION} ${D}/${KERNEL_IMAGEDEST}/${imageType}
|
||||
if [ $imageType != "fitImage" ] || [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ] ; then
|
||||
install -m 0644 ${KERNEL_OUTPUT_DIR}/${imageType} ${D}/${KERNEL_IMAGEDEST}/${imageType}-${KERNEL_VERSION}
|
||||
if [ "${KERNEL_PACKAGE_NAME}" = "kernel" ]; then
|
||||
ln -sf ${imageType}-${KERNEL_VERSION} ${D}/${KERNEL_IMAGEDEST}/${imageType}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
install -m 0644 System.map ${D}/boot/System.map-${KERNEL_VERSION}
|
||||
install -m 0644 .config ${D}/boot/config-${KERNEL_VERSION}
|
||||
install -m 0644 vmlinux ${D}/boot/vmlinux-${KERNEL_VERSION}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
# Zap the root password if debug-tweaks feature is not enabled
|
||||
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'empty-root-password' ], "", "zap_empty_root_password ; ",d)}'
|
||||
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'empty-root-password' ], "", "zap_empty_root_password; ",d)}'
|
||||
|
||||
# Allow dropbear/openssh to accept logins from accounts with an empty password string if debug-tweaks or allow-empty-password is enabled
|
||||
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'allow-empty-password' ], "ssh_allow_empty_password; ", "",d)}'
|
||||
@@ -12,7 +12,7 @@ ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'deb
|
||||
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'post-install-logging' ], "postinst_enable_logging; ", "",d)}'
|
||||
|
||||
# Create /etc/timestamp during image construction to give a reasonably sane default time setting
|
||||
ROOTFS_POSTPROCESS_COMMAND += "rootfs_update_timestamp ; "
|
||||
ROOTFS_POSTPROCESS_COMMAND += "rootfs_update_timestamp; "
|
||||
|
||||
# Tweak the mount options for rootfs in /etc/fstab if read-only-rootfs is enabled
|
||||
ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "read_only_rootfs_hook; ", "",d)}'
|
||||
@@ -26,7 +26,7 @@ ROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "read-only
|
||||
APPEND_append = '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", " ro", "", d)}'
|
||||
|
||||
# Generates test data file with data store variables expanded in json format
|
||||
ROOTFS_POSTPROCESS_COMMAND += "write_image_test_data ; "
|
||||
ROOTFS_POSTPROCESS_COMMAND += "write_image_test_data; "
|
||||
|
||||
# Write manifest
|
||||
IMAGE_MANIFEST = "${IMGDEPLOYDIR}/${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.manifest"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
ROOTFS_DEBUG_FILES ?= ""
|
||||
ROOTFS_DEBUG_FILES[doc] = "Lists additional files or directories to be installed with 'cp -a' in the format 'source1 target1;source2 target2;...'"
|
||||
|
||||
ROOTFS_POSTPROCESS_COMMAND += "rootfs_debug_files ;"
|
||||
ROOTFS_POSTPROCESS_COMMAND += "rootfs_debug_files;"
|
||||
rootfs_debug_files () {
|
||||
#!/bin/sh -e
|
||||
echo "${ROOTFS_DEBUG_FILES}" | sed -e 's/;/\n/g' | while read source target mode; do
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
# to the distro running on the build machine.
|
||||
#
|
||||
|
||||
UNINATIVE_MAXGLIBCVERSION = "2.37"
|
||||
UNINATIVE_VERSION = "4.0"
|
||||
UNINATIVE_MAXGLIBCVERSION = "2.38"
|
||||
UNINATIVE_VERSION = "4.3"
|
||||
|
||||
UNINATIVE_URL ?= "http://downloads.yoctoproject.org/releases/uninative/${UNINATIVE_VERSION}/"
|
||||
UNINATIVE_CHECKSUM[aarch64] ?= "7baa8418a302df52e00916193b0a04f318356d9d2670c9a2bce3e966efefd738"
|
||||
UNINATIVE_CHECKSUM[i686] ?= "83114d36883d43a521e280742b9849bf85d039b2f83d8e21d480659babe75ee8"
|
||||
UNINATIVE_CHECKSUM[x86_64] ?= "fd75b2a1a67a10f6b7d65afb7d0f3e71a63b0038e428f34dfe420bb37716558a"
|
||||
UNINATIVE_CHECKSUM[aarch64] ?= "8df05f4a41455018b4303b2e0ea4eac5c960b5a13713f6dbb33dfdb3e32753ec"
|
||||
UNINATIVE_CHECKSUM[i686] ?= "bea76b4a97c9ba0077c0dd1295f519cd599dbf71f0ca1c964471c4cdb043addd"
|
||||
UNINATIVE_CHECKSUM[x86_64] ?= "1c35f09a75c4096749bbe1e009df4e3968cde151424062cf4aa3ed89db22b030"
|
||||
|
||||
@@ -75,7 +75,7 @@ def cve_check_merge_jsons(output, data):
|
||||
|
||||
for product in output["package"]:
|
||||
if product["name"] == data["package"][0]["name"]:
|
||||
bb.error("Error adding the same package twice")
|
||||
bb.error("Error adding the same package %s twice" % product["name"])
|
||||
return
|
||||
|
||||
output["package"].append(data["package"][0])
|
||||
@@ -114,11 +114,6 @@ def get_patched_cves(d):
|
||||
for url in oe.patch.src_patches(d):
|
||||
patch_file = bb.fetch.decodeurl(url)[2]
|
||||
|
||||
# Remote compressed patches may not be unpacked, so silently ignore them
|
||||
if not os.path.isfile(patch_file):
|
||||
bb.warn("%s does not exist, cannot extract CVE list" % patch_file)
|
||||
continue
|
||||
|
||||
# Check patch file name for CVE ID
|
||||
fname_match = cve_file_name_match.search(patch_file)
|
||||
if fname_match:
|
||||
@@ -126,6 +121,12 @@ def get_patched_cves(d):
|
||||
patched_cves.add(cve)
|
||||
bb.debug(2, "Found CVE %s from patch file name %s" % (cve, patch_file))
|
||||
|
||||
# Remote patches won't be present and compressed patches won't be
|
||||
# unpacked, so say we're not scanning them
|
||||
if not os.path.isfile(patch_file):
|
||||
bb.note("%s is remote or compressed, not scanning content" % patch_file)
|
||||
continue
|
||||
|
||||
with open(patch_file, "r", encoding="utf-8") as f:
|
||||
try:
|
||||
patch_text = f.read()
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import oe.path
|
||||
import oe.types
|
||||
|
||||
@@ -24,7 +27,6 @@ class CmdError(bb.BBHandledException):
|
||||
|
||||
|
||||
def runcmd(args, dir = None):
|
||||
import pipes
|
||||
import subprocess
|
||||
|
||||
if dir:
|
||||
@@ -35,7 +37,7 @@ def runcmd(args, dir = None):
|
||||
# print("cwd: %s -> %s" % (olddir, dir))
|
||||
|
||||
try:
|
||||
args = [ pipes.quote(str(arg)) for arg in args ]
|
||||
args = [ shlex.quote(str(arg)) for arg in args ]
|
||||
cmd = " ".join(args)
|
||||
# print("cmd: %s" % cmd)
|
||||
(exitstatus, output) = subprocess.getstatusoutput(cmd)
|
||||
|
||||
@@ -226,6 +226,9 @@ def SSHCall(command, logger, timeout=None, **opts):
|
||||
endtime = time.time() + timeout
|
||||
except InterruptedError:
|
||||
continue
|
||||
except BlockingIOError:
|
||||
logger.debug('BlockingIOError')
|
||||
continue
|
||||
|
||||
# process hasn't returned yet
|
||||
if not eof:
|
||||
|
||||
@@ -67,7 +67,7 @@ class LtpTest(LtpTestBase):
|
||||
def runltp(self, ltp_group):
|
||||
cmd = '/opt/ltp/runltp -f %s -p -q -r /opt/ltp -l /opt/ltp/results/%s -I 1 -d /opt/ltp' % (ltp_group, ltp_group)
|
||||
starttime = time.time()
|
||||
(status, output) = self.target.run(cmd)
|
||||
(status, output) = self.target.run(cmd, timeout=1200)
|
||||
endtime = time.time()
|
||||
|
||||
with open(os.path.join(self.ltptest_log_dir, "%s-raw.log" % ltp_group), 'w') as f:
|
||||
|
||||
@@ -57,8 +57,8 @@ class RpmBasicTest(OERuntimeTestCase):
|
||||
return
|
||||
time.sleep(1)
|
||||
user_pss = [ps for ps in output.split("\n") if u + ' ' in ps]
|
||||
msg = "There're %s 's process(es) still running: %s".format(u, "\n".join(user_pss))
|
||||
assertTrue(True, msg=msg)
|
||||
msg = "User %s has processes still running: %s" % (u, "\n".join(user_pss))
|
||||
self.fail(msg=msg)
|
||||
|
||||
def unset_up_test_user(u):
|
||||
# ensure no test1 process in running
|
||||
|
||||
@@ -41,7 +41,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
|
||||
with contextlib.ExitStack() as s:
|
||||
# use the base work dir, as the nfs mount, since the recipe directory may not exist
|
||||
tmpdir = get_bb_var("BASE_WORKDIR")
|
||||
nfsport, mountport = s.enter_context(unfs_server(tmpdir))
|
||||
nfsport, mountport = s.enter_context(unfs_server(tmpdir, udp = False))
|
||||
|
||||
# build core-image-minimal with required packages
|
||||
default_installed_packages = [
|
||||
@@ -61,7 +61,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
|
||||
bitbake("core-image-minimal")
|
||||
|
||||
# start runqemu
|
||||
qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic"))
|
||||
qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic", qemuparams = "-m 1024"))
|
||||
|
||||
# validate that SSH is working
|
||||
status, _ = qemu.run("uname")
|
||||
@@ -70,7 +70,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
|
||||
# setup nfs mount
|
||||
if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0:
|
||||
raise Exception("Failed to setup NFS mount directory on target")
|
||||
mountcmd = "mount -o noac,nfsvers=3,port={0},udp,mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir)
|
||||
mountcmd = "mount -o noac,nfsvers=3,port={0},mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir)
|
||||
status, output = qemu.run(mountcmd)
|
||||
if status != 0:
|
||||
raise Exception("Failed to setup NFS mount on target ({})".format(repr(output)))
|
||||
|
||||
@@ -185,14 +185,8 @@ class TestImage(OESelftestTestCase):
|
||||
self.skipTest('virgl isn\'t working with Centos 7')
|
||||
if distro and distro == 'centos-8':
|
||||
self.skipTest('virgl isn\'t working with Centos 8')
|
||||
if distro and distro == 'fedora-34':
|
||||
self.skipTest('virgl isn\'t working with Fedora 34')
|
||||
if distro and distro == 'fedora-35':
|
||||
self.skipTest('virgl isn\'t working with Fedora 35')
|
||||
if distro and distro == 'fedora-36':
|
||||
self.skipTest('virgl isn\'t working with Fedora 36')
|
||||
if distro and distro == 'fedora-37':
|
||||
self.skipTest('virgl isn\'t working with Fedora 37')
|
||||
if distro and distro.startswith('fedora'):
|
||||
self.skipTest('virgl isn\'t working with Fedora')
|
||||
if distro and distro == 'opensuseleap-15.0':
|
||||
self.skipTest('virgl isn\'t working with Opensuse 15.0')
|
||||
if distro and distro == 'ubuntu-22.04':
|
||||
|
||||
@@ -8,7 +8,7 @@ from oeqa.utils.commands import bitbake, get_bb_var, Command
|
||||
from oeqa.utils.network import get_free_port
|
||||
|
||||
@contextlib.contextmanager
|
||||
def unfs_server(directory, logger = None):
|
||||
def unfs_server(directory, logger = None, udp = True):
|
||||
unfs_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "unfs3-native")
|
||||
if not os.path.exists(os.path.join(unfs_sysroot, "usr", "bin", "unfsd")):
|
||||
# build native tool
|
||||
@@ -22,7 +22,7 @@ def unfs_server(directory, logger = None):
|
||||
exports.write("{0} (rw,no_root_squash,no_all_squash,insecure)\n".format(directory).encode())
|
||||
|
||||
# find some ports for the server
|
||||
nfsport, mountport = get_free_port(udp = True), get_free_port(udp = True)
|
||||
nfsport, mountport = get_free_port(udp), get_free_port(udp)
|
||||
|
||||
nenv = dict(os.environ)
|
||||
nenv['PATH'] = "{0}/sbin:{0}/usr/sbin:{0}/usr/bin:".format(unfs_sysroot) + nenv.get('PATH', '')
|
||||
|
||||
97
meta/recipes-bsp/grub/files/CVE-2023-4692.patch
Normal file
97
meta/recipes-bsp/grub/files/CVE-2023-4692.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 43651027d24e62a7a463254165e1e46e42aecdea Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Date: Mon, 28 Aug 2023 16:31:57 +0300
|
||||
Subject: [PATCH] fs/ntfs: Fix an OOB write when parsing the $ATTRIBUTE_LIST
|
||||
attribute for the $MFT file
|
||||
|
||||
When parsing an extremely fragmented $MFT file, i.e., the file described
|
||||
using the $ATTRIBUTE_LIST attribute, current NTFS code will reuse a buffer
|
||||
containing bytes read from the underlying drive to store sector numbers,
|
||||
which are consumed later to read data from these sectors into another buffer.
|
||||
|
||||
These sectors numbers, two 32-bit integers, are always stored at predefined
|
||||
offsets, 0x10 and 0x14, relative to first byte of the selected entry within
|
||||
the $ATTRIBUTE_LIST attribute. Usually, this won't cause any problem.
|
||||
|
||||
However, when parsing a specially-crafted file system image, this may cause
|
||||
the NTFS code to write these integers beyond the buffer boundary, likely
|
||||
causing the GRUB memory allocator to misbehave or fail. These integers contain
|
||||
values which are controlled by on-disk structures of the NTFS file system.
|
||||
|
||||
Such modification and resulting misbehavior may touch a memory range not
|
||||
assigned to the GRUB and owned by firmware or another EFI application/driver.
|
||||
|
||||
This fix introduces checks to ensure that these sector numbers are never
|
||||
written beyond the boundary.
|
||||
|
||||
Fixes: CVE-2023-4692
|
||||
|
||||
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
|
||||
Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=43651027d24e62a7a463254165e1e46e42aecdea]
|
||||
CVE: CVE-2023-4692
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index 2f34f76..c8d3683 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -184,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
}
|
||||
if (at->attr_end)
|
||||
{
|
||||
- grub_uint8_t *pa;
|
||||
+ grub_uint8_t *pa, *pa_end;
|
||||
|
||||
at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
if (at->emft_buf == NULL)
|
||||
@@ -209,11 +209,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
}
|
||||
at->attr_nxt = at->edat_buf;
|
||||
at->attr_end = at->edat_buf + u32at (pa, 0x30);
|
||||
+ pa_end = at->edat_buf + n;
|
||||
}
|
||||
else
|
||||
{
|
||||
at->attr_nxt = at->attr_end + u16at (pa, 0x14);
|
||||
at->attr_end = at->attr_end + u32at (pa, 4);
|
||||
+ pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
|
||||
}
|
||||
at->flags |= GRUB_NTFS_AF_ALST;
|
||||
while (at->attr_nxt < at->attr_end)
|
||||
@@ -230,6 +232,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
at->flags |= GRUB_NTFS_AF_GPOS;
|
||||
at->attr_cur = at->attr_nxt;
|
||||
pa = at->attr_cur;
|
||||
+
|
||||
+ if ((pa >= pa_end) || (pa_end - pa < 0x18))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
grub_set_unaligned32 ((char *) pa + 0x10,
|
||||
grub_cpu_to_le32 (at->mft->data->mft_start));
|
||||
grub_set_unaligned32 ((char *) pa + 0x14,
|
||||
@@ -240,6 +249,13 @@ find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr)
|
||||
{
|
||||
if (*pa != attr)
|
||||
break;
|
||||
+
|
||||
+ if ((pa >= pa_end) || (pa_end - pa < 0x18))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (read_attr
|
||||
(at, pa + 0x10,
|
||||
u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
|
||||
--
|
||||
2.25.1
|
||||
|
||||
62
meta/recipes-bsp/grub/files/CVE-2023-4693.patch
Normal file
62
meta/recipes-bsp/grub/files/CVE-2023-4693.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0ed2458cc4eff6d9a9199527e2a0b6d445802f94 Mon Sep 17 00:00:00 2001
|
||||
From: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Date: Mon, 28 Aug 2023 16:32:33 +0300
|
||||
Subject: [PATCH] fs/ntfs: Fix an OOB read when reading data from the resident
|
||||
$DATA attribute
|
||||
|
||||
When reading a file containing resident data, i.e., the file data is stored in
|
||||
the $DATA attribute within the NTFS file record, not in external clusters,
|
||||
there are no checks that this resident data actually fits the corresponding
|
||||
file record segment.
|
||||
|
||||
When parsing a specially-crafted file system image, the current NTFS code will
|
||||
read the file data from an arbitrary, attacker-chosen memory offset and of
|
||||
arbitrary, attacker-chosen length.
|
||||
|
||||
This allows an attacker to display arbitrary chunks of memory, which could
|
||||
contain sensitive information like password hashes or even plain-text,
|
||||
obfuscated passwords from BS EFI variables.
|
||||
|
||||
This fix implements a check to ensure that resident data is read from the
|
||||
corresponding file record segment only.
|
||||
|
||||
Fixes: CVE-2023-4693
|
||||
|
||||
Reported-by: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
|
||||
Upstream-Status: Backport [https://git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=0ed2458cc4eff6d9a9199527e2a0b6d445802f94]
|
||||
CVE: CVE-2023-4693
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
grub-core/fs/ntfs.c | 13 ++++++++++++-
|
||||
1 file changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c
|
||||
index c8d3683..4d1fe42 100644
|
||||
--- a/grub-core/fs/ntfs.c
|
||||
+++ b/grub-core/fs/ntfs.c
|
||||
@@ -401,7 +401,18 @@ read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest,
|
||||
{
|
||||
if (ofs + len > u32at (pa, 0x10))
|
||||
return grub_error (GRUB_ERR_BAD_FS, "read out of range");
|
||||
- grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len);
|
||||
+
|
||||
+ if (u32at (pa, 0x10) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large");
|
||||
+
|
||||
+ if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR))
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
|
||||
+
|
||||
+ if (u16at (pa, 0x14) + u32at (pa, 0x10) >
|
||||
+ (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa)
|
||||
+ return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range");
|
||||
+
|
||||
+ grub_memcpy (dest, pa + u16at (pa, 0x14) + ofs, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -109,6 +109,8 @@ SRC_URI = "${GNU_MIRROR}/grub/grub-${PV}.tar.gz \
|
||||
file://CVE-2020-27749.patch \
|
||||
file://CVE-2021-20225.patch \
|
||||
file://CVE-2021-20233.patch \
|
||||
file://CVE-2023-4692.patch \
|
||||
file://CVE-2023-4693.patch \
|
||||
"
|
||||
SRC_URI[md5sum] = "5ce674ca6b2612d8939b9e6abed32934"
|
||||
SRC_URI[sha256sum] = "f10c85ae3e204dbaec39ae22fa3c5e99f0665417e91c2cb49b7e5031658ba6ea"
|
||||
@@ -128,6 +130,8 @@ GRUBPLATFORM ??= "pc"
|
||||
|
||||
inherit autotools gettext texinfo pkgconfig
|
||||
|
||||
CFLAGS_remove = "-O2"
|
||||
|
||||
EXTRA_OECONF = "--with-platform=${GRUBPLATFORM} \
|
||||
--disable-grub-mkfont \
|
||||
--program-prefix="" \
|
||||
|
||||
@@ -22,6 +22,15 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=2d5025d4aa3495befef8f17206a5b0a1 \
|
||||
SRC_URI = "https://github.com/lathiat/avahi/releases/download/v${PV}/avahi-${PV}.tar.gz \
|
||||
file://fix-CVE-2017-6519.patch \
|
||||
file://CVE-2021-3468.patch \
|
||||
file://CVE-2023-1981.patch \
|
||||
file://CVE-2023-38469-1.patch \
|
||||
file://CVE-2023-38469-2.patch \
|
||||
file://CVE-2023-38470-1.patch \
|
||||
file://CVE-2023-38470-2.patch \
|
||||
file://CVE-2023-38471-1.patch \
|
||||
file://CVE-2023-38471-2.patch \
|
||||
file://CVE-2023-38472.patch \
|
||||
file://CVE-2023-38473.patch \
|
||||
"
|
||||
|
||||
UPSTREAM_CHECK_URI = "https://github.com/lathiat/avahi/releases/"
|
||||
|
||||
60
meta/recipes-connectivity/avahi/files/CVE-2023-1981.patch
Normal file
60
meta/recipes-connectivity/avahi/files/CVE-2023-1981.patch
Normal file
@@ -0,0 +1,60 @@
|
||||
Backport of:
|
||||
|
||||
From a2696da2f2c50ac43b6c4903f72290d5c3fa9f6f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Thu, 17 Nov 2022 01:51:53 +0100
|
||||
Subject: [PATCH] Emit error if requested service is not found
|
||||
|
||||
It currently just crashes instead of replying with error. Check return
|
||||
value and emit error instead of passing NULL pointer to reply.
|
||||
|
||||
Fixes #375
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-1981.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/a2696da2f2c50ac43b6c4903f72290d5c3fa9f6f]
|
||||
CVE: CVE-2023-1981
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-daemon/dbus-protocol.c | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/avahi-daemon/dbus-protocol.c
|
||||
+++ b/avahi-daemon/dbus-protocol.c
|
||||
@@ -391,10 +391,14 @@ static DBusHandlerResult msg_server_impl
|
||||
}
|
||||
|
||||
t = avahi_alternative_host_name(n);
|
||||
- avahi_dbus_respond_string(c, m, t);
|
||||
- avahi_free(t);
|
||||
-
|
||||
- return DBUS_HANDLER_RESULT_HANDLED;
|
||||
+ if (t) {
|
||||
+ avahi_dbus_respond_string(c, m, t);
|
||||
+ avahi_free(t);
|
||||
+
|
||||
+ return DBUS_HANDLER_RESULT_HANDLED;
|
||||
+ } else {
|
||||
+ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Hostname not found");
|
||||
+ }
|
||||
|
||||
} else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
|
||||
char *n, *t;
|
||||
@@ -405,10 +409,14 @@ static DBusHandlerResult msg_server_impl
|
||||
}
|
||||
|
||||
t = avahi_alternative_service_name(n);
|
||||
- avahi_dbus_respond_string(c, m, t);
|
||||
- avahi_free(t);
|
||||
-
|
||||
- return DBUS_HANDLER_RESULT_HANDLED;
|
||||
+ if (t) {
|
||||
+ avahi_dbus_respond_string(c, m, t);
|
||||
+ avahi_free(t);
|
||||
+
|
||||
+ return DBUS_HANDLER_RESULT_HANDLED;
|
||||
+ } else {
|
||||
+ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Service not found");
|
||||
+ }
|
||||
|
||||
} else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
|
||||
Client *client;
|
||||
48
meta/recipes-connectivity/avahi/files/CVE-2023-38469-1.patch
Normal file
48
meta/recipes-connectivity/avahi/files/CVE-2023-38469-1.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From a337a1ba7d15853fb56deef1f464529af6e3a1cf Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Mon, 23 Oct 2023 20:29:31 +0000
|
||||
Subject: [PATCH] core: reject overly long TXT resource records
|
||||
|
||||
Closes https://github.com/lathiat/avahi/issues/455
|
||||
|
||||
CVE-2023-38469
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38469-1.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/a337a1ba7d15853fb56deef1f464529af6e3a1cf]
|
||||
CVE: CVE-2023-38469
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-core/rr.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: avahi-0.7/avahi-core/rr.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-core/rr.c
|
||||
+++ avahi-0.7/avahi-core/rr.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <avahi-common/malloc.h>
|
||||
#include <avahi-common/defs.h>
|
||||
|
||||
+#include "dns.h"
|
||||
#include "rr.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
@@ -688,11 +689,17 @@ int avahi_record_is_valid(AvahiRecord *r
|
||||
case AVAHI_DNS_TYPE_TXT: {
|
||||
|
||||
AvahiStringList *strlst;
|
||||
+ size_t used = 0;
|
||||
|
||||
- for (strlst = r->data.txt.string_list; strlst; strlst = strlst->next)
|
||||
+ for (strlst = r->data.txt.string_list; strlst; strlst = strlst->next) {
|
||||
if (strlst->size > 255 || strlst->size <= 0)
|
||||
return 0;
|
||||
|
||||
+ used += 1+strlst->size;
|
||||
+ if (used > AVAHI_DNS_RDATA_MAX)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
65
meta/recipes-connectivity/avahi/files/CVE-2023-38469-2.patch
Normal file
65
meta/recipes-connectivity/avahi/files/CVE-2023-38469-2.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
From c6cab87df290448a63323c8ca759baa516166237 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Wed, 25 Oct 2023 18:15:42 +0000
|
||||
Subject: [PATCH] tests: pass overly long TXT resource records
|
||||
|
||||
to make sure they don't crash avahi any more.
|
||||
It reproduces https://github.com/lathiat/avahi/issues/455
|
||||
|
||||
Canonical notes:
|
||||
nickgalanis> removed first hunk since there is no .github dir in this release
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38469-2.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/c6cab87df290448a63323c8ca759baa516166237]
|
||||
CVE: CVE-2023-38469
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-client/client-test.c | 14 ++++++++++++++
|
||||
1 files changed, 14 insertions(+)
|
||||
|
||||
Index: avahi-0.7/avahi-client/client-test.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-client/client-test.c
|
||||
+++ avahi-0.7/avahi-client/client-test.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
+#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <avahi-client/client.h>
|
||||
@@ -33,6 +34,8 @@
|
||||
#include <avahi-common/malloc.h>
|
||||
#include <avahi-common/timeval.h>
|
||||
|
||||
+#include <avahi-core/dns.h>
|
||||
+
|
||||
static const AvahiPoll *poll_api = NULL;
|
||||
static AvahiSimplePoll *simple_poll = NULL;
|
||||
|
||||
@@ -222,6 +225,9 @@ int main (AVAHI_GCC_UNUSED int argc, AVA
|
||||
uint32_t cookie;
|
||||
struct timeval tv;
|
||||
AvahiAddress a;
|
||||
+ uint8_t rdata[AVAHI_DNS_RDATA_MAX+1];
|
||||
+ AvahiStringList *txt = NULL;
|
||||
+ int r;
|
||||
|
||||
simple_poll = avahi_simple_poll_new();
|
||||
poll_api = avahi_simple_poll_get(simple_poll);
|
||||
@@ -258,6 +264,14 @@ int main (AVAHI_GCC_UNUSED int argc, AVA
|
||||
printf("%s\n", avahi_strerror(avahi_entry_group_add_service (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "Lathiat's Site", "_http._tcp", NULL, NULL, 80, "foo=bar", NULL)));
|
||||
printf("add_record: %d\n", avahi_entry_group_add_record (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "TestX", 0x01, 0x10, 120, "\5booya", 6));
|
||||
|
||||
+ memset(rdata, 1, sizeof(rdata));
|
||||
+ r = avahi_string_list_parse(rdata, sizeof(rdata), &txt);
|
||||
+ assert(r >= 0);
|
||||
+ assert(avahi_string_list_serialize(txt, NULL, 0) == sizeof(rdata));
|
||||
+ error = avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "TestX", "_qotd._tcp", NULL, NULL, 123, txt);
|
||||
+ assert(error == AVAHI_ERR_INVALID_RECORD);
|
||||
+ avahi_string_list_free(txt);
|
||||
+
|
||||
avahi_entry_group_commit (group);
|
||||
|
||||
domain = avahi_domain_browser_new (avahi, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, avahi_domain_browser_callback, (char*) "omghai3u");
|
||||
57
meta/recipes-connectivity/avahi/files/CVE-2023-38470-1.patch
Normal file
57
meta/recipes-connectivity/avahi/files/CVE-2023-38470-1.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From 94cb6489114636940ac683515417990b55b5d66c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
||||
Date: Tue, 11 Apr 2023 15:29:59 +0200
|
||||
Subject: [PATCH] Ensure each label is at least one byte long
|
||||
|
||||
The only allowed exception is single dot, where it should return empty
|
||||
string.
|
||||
|
||||
Fixes #454.
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38470-1.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/94cb6489114636940ac683515417990b55b5d66c]
|
||||
CVE: CVE-2023-38470
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-common/domain-test.c | 14 ++++++++++++++
|
||||
avahi-common/domain.c | 2 +-
|
||||
2 files changed, 15 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: avahi-0.7/avahi-common/domain-test.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-common/domain-test.c
|
||||
+++ avahi-0.7/avahi-common/domain-test.c
|
||||
@@ -45,6 +45,20 @@ int main(AVAHI_GCC_UNUSED int argc, AVAH
|
||||
printf("%s\n", s = avahi_normalize_name_strdup("fo\\\\o\\..f oo."));
|
||||
avahi_free(s);
|
||||
|
||||
+ printf("%s\n", s = avahi_normalize_name_strdup("."));
|
||||
+ avahi_free(s);
|
||||
+
|
||||
+ s = avahi_normalize_name_strdup(",.=.}.=.?-.}.=.?.?.}.}.?.?.?.z.?.?.}.}."
|
||||
+ "}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.=.=.?.?.}.}.?.?.}.}.}"
|
||||
+ ".?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.=.=.?.?.}.}.?.?.?.zM.?`"
|
||||
+ "?.}.}.}.?.?.?.r.=.?.}.=.?.?.}.?.?.?.}.=.?.?.}??.}.}.?.?."
|
||||
+ "?.z.?.?.}.}.}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.?`?.}.}.}."
|
||||
+ "??.?.zM.?`?.}.}.}.?.?.?.r.=.?.}.=.?.?.}.?.?.?.}.=.?.?.}?"
|
||||
+ "?.}.}.?.?.?.z.?.?.}.}.}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM."
|
||||
+ "?`?.}.}.}.?.?.?.r.=.=.?.?`.?.?}.}.}.?.?.?.r.=.?.}.=.?.?."
|
||||
+ "}.?.?.?.}.=.?.?.}");
|
||||
+ assert(s == NULL);
|
||||
+
|
||||
printf("%i\n", avahi_domain_equal("\\065aa bbb\\.\\046cc.cc\\\\.dee.fff.", "Aaa BBB\\.\\.cc.cc\\\\.dee.fff"));
|
||||
printf("%i\n", avahi_domain_equal("A", "a"));
|
||||
|
||||
Index: avahi-0.7/avahi-common/domain.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-common/domain.c
|
||||
+++ avahi-0.7/avahi-common/domain.c
|
||||
@@ -201,7 +201,7 @@ char *avahi_normalize_name(const char *s
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
- if (size < 1)
|
||||
+ if (size < 2)
|
||||
return NULL;
|
||||
|
||||
*(r++) = '.';
|
||||
53
meta/recipes-connectivity/avahi/files/CVE-2023-38470-2.patch
Normal file
53
meta/recipes-connectivity/avahi/files/CVE-2023-38470-2.patch
Normal file
@@ -0,0 +1,53 @@
|
||||
From 20dec84b2480821704258bc908e7b2bd2e883b24 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Tue, 19 Sep 2023 03:21:25 +0000
|
||||
Subject: [PATCH] [common] bail out when escaped labels can't fit into ret
|
||||
|
||||
Fixes:
|
||||
```
|
||||
==93410==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7f9e76f14c16 at pc 0x00000047208d bp 0x7ffee90a6a00 sp 0x7ffee90a61c8
|
||||
READ of size 1110 at 0x7f9e76f14c16 thread T0
|
||||
#0 0x47208c in __interceptor_strlen (out/fuzz-domain+0x47208c) (BuildId: 731b20c1eef22c2104e75a6496a399b10cfc7cba)
|
||||
#1 0x534eb0 in avahi_strdup avahi/avahi-common/malloc.c:167:12
|
||||
#2 0x53862c in avahi_normalize_name_strdup avahi/avahi-common/domain.c:226:12
|
||||
```
|
||||
and
|
||||
```
|
||||
fuzz-domain: fuzz/fuzz-domain.c:38: int LLVMFuzzerTestOneInput(const uint8_t *, size_t): Assertion `avahi_domain_equal(s, t)' failed.
|
||||
==101571== ERROR: libFuzzer: deadly signal
|
||||
#0 0x501175 in __sanitizer_print_stack_trace (/home/vagrant/avahi/out/fuzz-domain+0x501175) (BuildId: 682bf6400aff9d41b64b6e2cc3ef5ad600216ea8)
|
||||
#1 0x45ad2c in fuzzer::PrintStackTrace() (/home/vagrant/avahi/out/fuzz-domain+0x45ad2c) (BuildId: 682bf6400aff9d41b64b6e2cc3ef5ad600216ea8)
|
||||
#2 0x43fc07 in fuzzer::Fuzzer::CrashCallback() (/home/vagrant/avahi/out/fuzz-domain+0x43fc07) (BuildId: 682bf6400aff9d41b64b6e2cc3ef5ad600216ea8)
|
||||
#3 0x7f1581d7ebaf (/lib64/libc.so.6+0x3dbaf) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#4 0x7f1581dcf883 in __pthread_kill_implementation (/lib64/libc.so.6+0x8e883) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#5 0x7f1581d7eafd in gsignal (/lib64/libc.so.6+0x3dafd) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#6 0x7f1581d6787e in abort (/lib64/libc.so.6+0x2687e) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#7 0x7f1581d6779a in __assert_fail_base.cold (/lib64/libc.so.6+0x2679a) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#8 0x7f1581d77186 in __assert_fail (/lib64/libc.so.6+0x36186) (BuildId: c9f62793b9e886eb1b95077d4f26fe2b4aa1ac25)
|
||||
#9 0x5344a4 in LLVMFuzzerTestOneInput /home/vagrant/avahi/fuzz/fuzz-domain.c:38:9
|
||||
```
|
||||
|
||||
It's a follow-up to 94cb6489114636940ac683515417990b55b5d66c
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38471-2.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/20dec84b2480821704258bc908e7b2bd2e883b24]
|
||||
CVE: CVE-2023-38470 #Follow-up patch
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-common/domain.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: avahi-0.7/avahi-common/domain.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-common/domain.c
|
||||
+++ avahi-0.7/avahi-common/domain.c
|
||||
@@ -210,7 +210,8 @@ char *avahi_normalize_name(const char *s
|
||||
} else
|
||||
empty = 0;
|
||||
|
||||
- avahi_escape_label(label, strlen(label), &r, &size);
|
||||
+ if (!(avahi_escape_label(label, strlen(label), &r, &size)))
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
return ret_s;
|
||||
73
meta/recipes-connectivity/avahi/files/CVE-2023-38471-1.patch
Normal file
73
meta/recipes-connectivity/avahi/files/CVE-2023-38471-1.patch
Normal file
@@ -0,0 +1,73 @@
|
||||
From 894f085f402e023a98cbb6f5a3d117bd88d93b09 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 23 Oct 2023 13:38:35 +0200
|
||||
Subject: [PATCH] core: extract host name using avahi_unescape_label()
|
||||
|
||||
Previously we could create invalid escape sequence when we split the
|
||||
string on dot. For example, from valid host name "foo\\.bar" we have
|
||||
created invalid name "foo\\" and tried to set that as the host name
|
||||
which crashed the daemon.
|
||||
|
||||
Fixes #453
|
||||
|
||||
CVE-2023-38471
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38471-1.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/894f085f402e023a98cbb6f5a3d117bd88d93b09]
|
||||
CVE: CVE-2023-38471
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-core/server.c | 27 +++++++++++++++++++++------
|
||||
1 file changed, 21 insertions(+), 6 deletions(-)
|
||||
|
||||
Index: avahi-0.7/avahi-core/server.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-core/server.c
|
||||
+++ avahi-0.7/avahi-core/server.c
|
||||
@@ -1253,7 +1253,11 @@ static void update_fqdn(AvahiServer *s)
|
||||
}
|
||||
|
||||
int avahi_server_set_host_name(AvahiServer *s, const char *host_name) {
|
||||
- char *hn = NULL;
|
||||
+ char label_escaped[AVAHI_LABEL_MAX*4+1];
|
||||
+ char label[AVAHI_LABEL_MAX];
|
||||
+ char *hn = NULL, *h;
|
||||
+ size_t len;
|
||||
+
|
||||
assert(s);
|
||||
|
||||
AVAHI_CHECK_VALIDITY(s, !host_name || avahi_is_valid_host_name(host_name), AVAHI_ERR_INVALID_HOST_NAME);
|
||||
@@ -1263,17 +1267,28 @@ int avahi_server_set_host_name(AvahiServ
|
||||
else
|
||||
hn = avahi_normalize_name_strdup(host_name);
|
||||
|
||||
- hn[strcspn(hn, ".")] = 0;
|
||||
+ h = hn;
|
||||
+ if (!avahi_unescape_label((const char **)&hn, label, sizeof(label))) {
|
||||
+ avahi_free(h);
|
||||
+ return AVAHI_ERR_INVALID_HOST_NAME;
|
||||
+ }
|
||||
+
|
||||
+ avahi_free(h);
|
||||
|
||||
- if (avahi_domain_equal(s->host_name, hn) && s->state != AVAHI_SERVER_COLLISION) {
|
||||
- avahi_free(hn);
|
||||
+ h = label_escaped;
|
||||
+ len = sizeof(label_escaped);
|
||||
+ if (!avahi_escape_label(label, strlen(label), &h, &len))
|
||||
+ return AVAHI_ERR_INVALID_HOST_NAME;
|
||||
+
|
||||
+ if (avahi_domain_equal(s->host_name, label_escaped) && s->state != AVAHI_SERVER_COLLISION)
|
||||
return avahi_server_set_errno(s, AVAHI_ERR_NO_CHANGE);
|
||||
- }
|
||||
|
||||
withdraw_host_rrs(s);
|
||||
|
||||
avahi_free(s->host_name);
|
||||
- s->host_name = hn;
|
||||
+ s->host_name = avahi_strdup(label_escaped);
|
||||
+ if (!s->host_name)
|
||||
+ return AVAHI_ERR_NO_MEMORY;
|
||||
|
||||
update_fqdn(s);
|
||||
|
||||
52
meta/recipes-connectivity/avahi/files/CVE-2023-38471-2.patch
Normal file
52
meta/recipes-connectivity/avahi/files/CVE-2023-38471-2.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From b675f70739f404342f7f78635d6e2dcd85a13460 Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Tue, 24 Oct 2023 22:04:51 +0000
|
||||
Subject: [PATCH] core: return errors from avahi_server_set_host_name properly
|
||||
|
||||
It's a follow-up to 894f085f402e023a98cbb6f5a3d117bd88d93b09
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38471-2.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/b675f70739f404342f7f78635d6e2dcd85a13460]
|
||||
CVE: CVE-2023-38471 #Follow-up Patch
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-core/server.c | 9 ++++++---
|
||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
Index: avahi-0.7/avahi-core/server.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-core/server.c
|
||||
+++ avahi-0.7/avahi-core/server.c
|
||||
@@ -1267,10 +1267,13 @@ int avahi_server_set_host_name(AvahiServ
|
||||
else
|
||||
hn = avahi_normalize_name_strdup(host_name);
|
||||
|
||||
+ if (!hn)
|
||||
+ return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);
|
||||
+
|
||||
h = hn;
|
||||
if (!avahi_unescape_label((const char **)&hn, label, sizeof(label))) {
|
||||
avahi_free(h);
|
||||
- return AVAHI_ERR_INVALID_HOST_NAME;
|
||||
+ return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
|
||||
}
|
||||
|
||||
avahi_free(h);
|
||||
@@ -1278,7 +1281,7 @@ int avahi_server_set_host_name(AvahiServ
|
||||
h = label_escaped;
|
||||
len = sizeof(label_escaped);
|
||||
if (!avahi_escape_label(label, strlen(label), &h, &len))
|
||||
- return AVAHI_ERR_INVALID_HOST_NAME;
|
||||
+ return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
|
||||
|
||||
if (avahi_domain_equal(s->host_name, label_escaped) && s->state != AVAHI_SERVER_COLLISION)
|
||||
return avahi_server_set_errno(s, AVAHI_ERR_NO_CHANGE);
|
||||
@@ -1288,7 +1291,7 @@ int avahi_server_set_host_name(AvahiServ
|
||||
avahi_free(s->host_name);
|
||||
s->host_name = avahi_strdup(label_escaped);
|
||||
if (!s->host_name)
|
||||
- return AVAHI_ERR_NO_MEMORY;
|
||||
+ return avahi_server_set_errno(s, AVAHI_ERR_NO_MEMORY);
|
||||
|
||||
update_fqdn(s);
|
||||
|
||||
45
meta/recipes-connectivity/avahi/files/CVE-2023-38472.patch
Normal file
45
meta/recipes-connectivity/avahi/files/CVE-2023-38472.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From b024ae5749f4aeba03478e6391687c3c9c8dee40 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Thu, 19 Oct 2023 17:36:44 +0200
|
||||
Subject: [PATCH] core: make sure there is rdata to process before parsing it
|
||||
|
||||
Fixes #452
|
||||
|
||||
CVE-2023-38472
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38472.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/b024ae5749f4aeba03478e6391687c3c9c8dee40]
|
||||
CVE: CVE-2023-38472
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-client/client-test.c | 3 +++
|
||||
avahi-daemon/dbus-entry-group.c | 2 +-
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
Index: avahi-0.7/avahi-client/client-test.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-client/client-test.c
|
||||
+++ avahi-0.7/avahi-client/client-test.c
|
||||
@@ -272,6 +272,9 @@ int main (AVAHI_GCC_UNUSED int argc, AVA
|
||||
assert(error == AVAHI_ERR_INVALID_RECORD);
|
||||
avahi_string_list_free(txt);
|
||||
|
||||
+ error = avahi_entry_group_add_record (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "TestX", 0x01, 0x10, 120, "", 0);
|
||||
+ assert(error != AVAHI_OK);
|
||||
+
|
||||
avahi_entry_group_commit (group);
|
||||
|
||||
domain = avahi_domain_browser_new (avahi, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, avahi_domain_browser_callback, (char*) "omghai3u");
|
||||
Index: avahi-0.7/avahi-daemon/dbus-entry-group.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-daemon/dbus-entry-group.c
|
||||
+++ avahi-0.7/avahi-daemon/dbus-entry-group.c
|
||||
@@ -340,7 +340,7 @@ DBusHandlerResult avahi_dbus_msg_entry_g
|
||||
if (!(r = avahi_record_new_full (name, clazz, type, ttl)))
|
||||
return avahi_dbus_respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL);
|
||||
|
||||
- if (avahi_rdata_parse (r, rdata, size) < 0) {
|
||||
+ if (!rdata || avahi_rdata_parse (r, rdata, size) < 0) {
|
||||
avahi_record_unref (r);
|
||||
return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL);
|
||||
}
|
||||
109
meta/recipes-connectivity/avahi/files/CVE-2023-38473.patch
Normal file
109
meta/recipes-connectivity/avahi/files/CVE-2023-38473.patch
Normal file
@@ -0,0 +1,109 @@
|
||||
From b448c9f771bada14ae8de175695a9729f8646797 Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Wed, 11 Oct 2023 17:45:44 +0200
|
||||
Subject: [PATCH] common: derive alternative host name from its unescaped
|
||||
version
|
||||
|
||||
Normalization of input makes sure we don't have to deal with special
|
||||
cases like unescaped dot at the end of label.
|
||||
|
||||
Fixes #451 #487
|
||||
CVE-2023-38473
|
||||
|
||||
Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/avahi/tree/debian/patches/CVE-2023-38473.patch?h=ubuntu/focal-security
|
||||
Upstream commit https://github.com/lathiat/avahi/commit/b448c9f771bada14ae8de175695a9729f8646797]
|
||||
CVE: CVE-2023-38473
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
avahi-common/alternative-test.c | 3 +++
|
||||
avahi-common/alternative.c | 27 +++++++++++++++++++--------
|
||||
2 files changed, 22 insertions(+), 8 deletions(-)
|
||||
|
||||
Index: avahi-0.7/avahi-common/alternative-test.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-common/alternative-test.c
|
||||
+++ avahi-0.7/avahi-common/alternative-test.c
|
||||
@@ -31,6 +31,9 @@ int main(AVAHI_GCC_UNUSED int argc, AVAH
|
||||
const char* const test_strings[] = {
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXüüüüüüü",
|
||||
+ ").",
|
||||
+ "\\.",
|
||||
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\\",
|
||||
"gurke",
|
||||
"-",
|
||||
" #",
|
||||
Index: avahi-0.7/avahi-common/alternative.c
|
||||
===================================================================
|
||||
--- avahi-0.7.orig/avahi-common/alternative.c
|
||||
+++ avahi-0.7/avahi-common/alternative.c
|
||||
@@ -49,15 +49,20 @@ static void drop_incomplete_utf8(char *c
|
||||
}
|
||||
|
||||
char *avahi_alternative_host_name(const char *s) {
|
||||
+ char label[AVAHI_LABEL_MAX], alternative[AVAHI_LABEL_MAX*4+1];
|
||||
+ char *alt, *r, *ret;
|
||||
const char *e;
|
||||
- char *r;
|
||||
+ size_t len;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (!avahi_is_valid_host_name(s))
|
||||
return NULL;
|
||||
|
||||
- if ((e = strrchr(s, '-'))) {
|
||||
+ if (!avahi_unescape_label(&s, label, sizeof(label)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if ((e = strrchr(label, '-'))) {
|
||||
const char *p;
|
||||
|
||||
e++;
|
||||
@@ -74,19 +79,18 @@ char *avahi_alternative_host_name(const
|
||||
|
||||
if (e) {
|
||||
char *c, *m;
|
||||
- size_t l;
|
||||
int n;
|
||||
|
||||
n = atoi(e)+1;
|
||||
if (!(m = avahi_strdup_printf("%i", n)))
|
||||
return NULL;
|
||||
|
||||
- l = e-s-1;
|
||||
+ len = e-label-1;
|
||||
|
||||
- if (l >= AVAHI_LABEL_MAX-1-strlen(m)-1)
|
||||
- l = AVAHI_LABEL_MAX-1-strlen(m)-1;
|
||||
+ if (len >= AVAHI_LABEL_MAX-1-strlen(m)-1)
|
||||
+ len = AVAHI_LABEL_MAX-1-strlen(m)-1;
|
||||
|
||||
- if (!(c = avahi_strndup(s, l))) {
|
||||
+ if (!(c = avahi_strndup(label, len))) {
|
||||
avahi_free(m);
|
||||
return NULL;
|
||||
}
|
||||
@@ -100,7 +104,7 @@ char *avahi_alternative_host_name(const
|
||||
} else {
|
||||
char *c;
|
||||
|
||||
- if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-2)))
|
||||
+ if (!(c = avahi_strndup(label, AVAHI_LABEL_MAX-1-2)))
|
||||
return NULL;
|
||||
|
||||
drop_incomplete_utf8(c);
|
||||
@@ -109,6 +113,13 @@ char *avahi_alternative_host_name(const
|
||||
avahi_free(c);
|
||||
}
|
||||
|
||||
+ alt = alternative;
|
||||
+ len = sizeof(alternative);
|
||||
+ ret = avahi_escape_label(r, strlen(r), &alt, &len);
|
||||
+
|
||||
+ avahi_free(r);
|
||||
+ r = avahi_strdup(ret);
|
||||
+
|
||||
assert(avahi_is_valid_host_name(r));
|
||||
|
||||
return r;
|
||||
166
meta/recipes-connectivity/bind/bind/CVE-2023-2828.patch
Normal file
166
meta/recipes-connectivity/bind/bind/CVE-2023-2828.patch
Normal file
@@ -0,0 +1,166 @@
|
||||
|
||||
Upstream-Status: Backport [import from debian security.debian.org/debian-security/pool/updates/main/b/bind9/bind9_9.11.5.P4+dfsg-5.1+deb10u9.debian.tar.xz
|
||||
Upstream patch https://downloads.isc.org/isc/bind9/9.16.42/patches/0001-CVE-2023-2828.patch]
|
||||
Upstream Commit: https://github.com/isc-projects/bind9/commit/da0eafcdee52147e72d407cc3b9f179378ee1d3a
|
||||
CVE: CVE-2023-2828
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
|
||||
---
|
||||
lib/dns/rbtdb.c | 106 +++++++++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 63 insertions(+), 43 deletions(-)
|
||||
|
||||
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
|
||||
index b1b928c..3165e26 100644
|
||||
--- a/lib/dns/rbtdb.c
|
||||
+++ b/lib/dns/rbtdb.c
|
||||
@@ -792,7 +792,7 @@ static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
|
||||
static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
|
||||
bool tree_locked, expire_t reason);
|
||||
static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
|
||||
- isc_stdtime_t now, bool tree_locked);
|
||||
+ size_t purgesize, bool tree_locked);
|
||||
static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
|
||||
rdatasetheader_t *newheader);
|
||||
static void resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
|
||||
@@ -6784,6 +6784,16 @@ addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||||
|
||||
static dns_dbmethods_t zone_methods;
|
||||
|
||||
+static size_t
|
||||
+rdataset_size(rdatasetheader_t *header) {
|
||||
+ if (!NONEXISTENT(header)) {
|
||||
+ return (dns_rdataslab_size((unsigned char *)header,
|
||||
+ sizeof(*header)));
|
||||
+ }
|
||||
+
|
||||
+ return (sizeof(*header));
|
||||
+}
|
||||
+
|
||||
static isc_result_t
|
||||
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
|
||||
@@ -6932,7 +6942,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
}
|
||||
|
||||
if (cache_is_overmem)
|
||||
- overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked);
|
||||
+ overmem_purge(rbtdb, rbtnode->locknum, rdataset_size(newheader),
|
||||
+ tree_locked);
|
||||
|
||||
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
@@ -6947,9 +6958,14 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
cleanup_dead_nodes(rbtdb, rbtnode->locknum);
|
||||
|
||||
header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
|
||||
- if (header && header->rdh_ttl < now - RBTDB_VIRTUAL)
|
||||
- expire_header(rbtdb, header, tree_locked,
|
||||
- expire_ttl);
|
||||
+ if (header != NULL) {
|
||||
+ dns_ttl_t rdh_ttl = header->rdh_ttl;
|
||||
+
|
||||
+ if (rdh_ttl < now - RBTDB_VIRTUAL) {
|
||||
+ expire_header(rbtdb, header, tree_locked,
|
||||
+ expire_ttl);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/*
|
||||
* If we've been holding a write lock on the tree just for
|
||||
@@ -10388,54 +10404,58 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
|
||||
ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link);
|
||||
}
|
||||
|
||||
+static size_t
|
||||
+expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, size_t purgesize,
|
||||
+ bool tree_locked) {
|
||||
+ rdatasetheader_t *header, *header_prev;
|
||||
+ size_t purged = 0;
|
||||
+
|
||||
+ for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
|
||||
+ header != NULL && purged <= purgesize; header = header_prev)
|
||||
+ {
|
||||
+ header_prev = ISC_LIST_PREV(header, link);
|
||||
+ /*
|
||||
+ * Unlink the entry at this point to avoid checking it
|
||||
+ * again even if it's currently used someone else and
|
||||
+ * cannot be purged at this moment. This entry won't be
|
||||
+ * referenced any more (so unlinking is safe) since the
|
||||
+ * TTL was reset to 0.
|
||||
+ */
|
||||
+ ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, link);
|
||||
+ size_t header_size = rdataset_size(header);
|
||||
+ expire_header(rbtdb, header, tree_locked, expire_lru);
|
||||
+ purged += header_size;
|
||||
+ }
|
||||
+
|
||||
+ return (purged);
|
||||
+}
|
||||
+
|
||||
/*%
|
||||
- * Purge some expired and/or stale (i.e. unused for some period) cache entries
|
||||
- * under an overmem condition. To recover from this condition quickly, up to
|
||||
- * 2 entries will be purged. This process is triggered while adding a new
|
||||
- * entry, and we specifically avoid purging entries in the same LRU bucket as
|
||||
- * the one to which the new entry will belong. Otherwise, we might purge
|
||||
- * entries of the same name of different RR types while adding RRsets from a
|
||||
- * single response (consider the case where we're adding A and AAAA glue records
|
||||
- * of the same NS name).
|
||||
- */
|
||||
+ * Purge some stale (i.e. unused for some period - LRU based cleaning) cache
|
||||
+ * entries under the overmem condition. To recover from this condition quickly,
|
||||
+ * we cleanup entries up to the size of newly added rdata (passed as purgesize).
|
||||
+ *
|
||||
+ * This process is triggered while adding a new entry, and we specifically avoid
|
||||
+ * purging entries in the same LRU bucket as the one to which the new entry will
|
||||
+ * belong. Otherwise, we might purge entries of the same name of different RR
|
||||
+ * types while adding RRsets from a single response (consider the case where
|
||||
+ * we're adding A and AAAA glue records of the same NS name).
|
||||
+*/
|
||||
static void
|
||||
-overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
|
||||
- isc_stdtime_t now, bool tree_locked)
|
||||
+overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, size_t purgesize,
|
||||
+ bool tree_locked)
|
||||
{
|
||||
- rdatasetheader_t *header, *header_prev;
|
||||
unsigned int locknum;
|
||||
- int purgecount = 2;
|
||||
+ size_t purged = 0;
|
||||
|
||||
for (locknum = (locknum_start + 1) % rbtdb->node_lock_count;
|
||||
- locknum != locknum_start && purgecount > 0;
|
||||
+ locknum != locknum_start && purged <= purgesize;
|
||||
locknum = (locknum + 1) % rbtdb->node_lock_count) {
|
||||
NODE_LOCK(&rbtdb->node_locks[locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
|
||||
- header = isc_heap_element(rbtdb->heaps[locknum], 1);
|
||||
- if (header && header->rdh_ttl < now - RBTDB_VIRTUAL) {
|
||||
- expire_header(rbtdb, header, tree_locked,
|
||||
- expire_ttl);
|
||||
- purgecount--;
|
||||
- }
|
||||
-
|
||||
- for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
|
||||
- header != NULL && purgecount > 0;
|
||||
- header = header_prev) {
|
||||
- header_prev = ISC_LIST_PREV(header, link);
|
||||
- /*
|
||||
- * Unlink the entry at this point to avoid checking it
|
||||
- * again even if it's currently used someone else and
|
||||
- * cannot be purged at this moment. This entry won't be
|
||||
- * referenced any more (so unlinking is safe) since the
|
||||
- * TTL was reset to 0.
|
||||
- */
|
||||
- ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header,
|
||||
- link);
|
||||
- expire_header(rbtdb, header, tree_locked,
|
||||
- expire_lru);
|
||||
- purgecount--;
|
||||
- }
|
||||
+ purged += expire_lru_headers(rbtdb, locknum, purgesize - purged,
|
||||
+ tree_locked);
|
||||
|
||||
NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
|
||||
isc_rwlocktype_write);
|
||||
175
meta/recipes-connectivity/bind/bind/CVE-2023-3341.patch
Normal file
175
meta/recipes-connectivity/bind/bind/CVE-2023-3341.patch
Normal file
@@ -0,0 +1,175 @@
|
||||
From c4fac5ca98efd02fbaef43601627c7a3a09f5a71 Mon Sep 17 00:00:00 2001
|
||||
From: Mark Andrews <marka@isc.org>
|
||||
Date: Tue, 20 Jun 2023 15:21:36 +1000
|
||||
Subject: [PATCH] Limit isccc_cc_fromwire recursion depth
|
||||
|
||||
Named and rndc do not need a lot of recursion so the depth is
|
||||
set to 10.
|
||||
|
||||
Taken from BIND 9.16.44 change.
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.isc.org/isc-projects/bind9/-/commit/c4fac5ca98efd02fbaef43601627c7a3a09f5a71]
|
||||
CVE: CVE-2023-3341
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
lib/isccc/cc.c | 38 +++++++++++++++++++++++---------
|
||||
lib/isccc/include/isccc/result.h | 4 +++-
|
||||
lib/isccc/result.c | 4 +++-
|
||||
3 files changed, 34 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c
|
||||
index e012685..8eac3d6 100644
|
||||
--- a/lib/isccc/cc.c
|
||||
+++ b/lib/isccc/cc.c
|
||||
@@ -53,6 +53,10 @@
|
||||
|
||||
#define MAX_TAGS 256
|
||||
#define DUP_LIFETIME 900
|
||||
+#ifndef ISCCC_MAXDEPTH
|
||||
+#define ISCCC_MAXDEPTH \
|
||||
+ 10 /* Big enough for rndc which just sends a string each way. */
|
||||
+#endif
|
||||
|
||||
typedef isccc_sexpr_t *sexpr_ptr;
|
||||
|
||||
@@ -561,19 +565,25 @@ verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length,
|
||||
|
||||
static isc_result_t
|
||||
table_fromwire(isccc_region_t *source, isccc_region_t *secret,
|
||||
- uint32_t algorithm, isccc_sexpr_t **alistp);
|
||||
+ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp);
|
||||
|
||||
static isc_result_t
|
||||
-list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp);
|
||||
+list_fromwire(isccc_region_t *source, unsigned int depth,
|
||||
+ isccc_sexpr_t **listp);
|
||||
|
||||
static isc_result_t
|
||||
-value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
|
||||
+value_fromwire(isccc_region_t *source, unsigned int depth,
|
||||
+ isccc_sexpr_t **valuep) {
|
||||
unsigned int msgtype;
|
||||
uint32_t len;
|
||||
isccc_sexpr_t *value;
|
||||
isccc_region_t active;
|
||||
isc_result_t result;
|
||||
|
||||
+ if (depth > ISCCC_MAXDEPTH) {
|
||||
+ return (ISCCC_R_MAXDEPTH);
|
||||
+ }
|
||||
+
|
||||
if (REGION_SIZE(*source) < 1 + 4)
|
||||
return (ISC_R_UNEXPECTEDEND);
|
||||
GET8(msgtype, source->rstart);
|
||||
@@ -591,9 +601,9 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
|
||||
} else
|
||||
result = ISC_R_NOMEMORY;
|
||||
} else if (msgtype == ISCCC_CCMSGTYPE_TABLE)
|
||||
- result = table_fromwire(&active, NULL, 0, valuep);
|
||||
+ result = table_fromwire(&active, NULL, 0, depth + 1, valuep);
|
||||
else if (msgtype == ISCCC_CCMSGTYPE_LIST)
|
||||
- result = list_fromwire(&active, valuep);
|
||||
+ result = list_fromwire(&active, depth + 1, valuep);
|
||||
else
|
||||
result = ISCCC_R_SYNTAX;
|
||||
|
||||
@@ -602,7 +612,7 @@ value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) {
|
||||
|
||||
static isc_result_t
|
||||
table_fromwire(isccc_region_t *source, isccc_region_t *secret,
|
||||
- uint32_t algorithm, isccc_sexpr_t **alistp)
|
||||
+ uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp)
|
||||
{
|
||||
char key[256];
|
||||
uint32_t len;
|
||||
@@ -613,6 +623,10 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret,
|
||||
|
||||
REQUIRE(alistp != NULL && *alistp == NULL);
|
||||
|
||||
+ if (depth > ISCCC_MAXDEPTH) {
|
||||
+ return (ISCCC_R_MAXDEPTH);
|
||||
+ }
|
||||
+
|
||||
checksum_rstart = NULL;
|
||||
first_tag = true;
|
||||
alist = isccc_alist_create();
|
||||
@@ -628,7 +642,7 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret,
|
||||
GET_MEM(key, len, source->rstart);
|
||||
key[len] = '\0'; /* Ensure NUL termination. */
|
||||
value = NULL;
|
||||
- result = value_fromwire(source, &value);
|
||||
+ result = value_fromwire(source, depth + 1, &value);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto bad;
|
||||
if (isccc_alist_define(alist, key, value) == NULL) {
|
||||
@@ -661,14 +675,18 @@ table_fromwire(isccc_region_t *source, isccc_region_t *secret,
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
-list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp) {
|
||||
+list_fromwire(isccc_region_t *source, unsigned int depth, isccc_sexpr_t **listp) {
|
||||
isccc_sexpr_t *list, *value;
|
||||
isc_result_t result;
|
||||
|
||||
+ if (depth > ISCCC_MAXDEPTH) {
|
||||
+ return (ISCCC_R_MAXDEPTH);
|
||||
+ }
|
||||
+
|
||||
list = NULL;
|
||||
while (!REGION_EMPTY(*source)) {
|
||||
value = NULL;
|
||||
- result = value_fromwire(source, &value);
|
||||
+ result = value_fromwire(source, depth + 1, &value);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isccc_sexpr_free(&list);
|
||||
return (result);
|
||||
@@ -699,7 +717,7 @@ isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp,
|
||||
if (version != 1)
|
||||
return (ISCCC_R_UNKNOWNVERSION);
|
||||
|
||||
- return (table_fromwire(source, secret, algorithm, alistp));
|
||||
+ return (table_fromwire(source, secret, algorithm, 0, alistp));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
diff --git a/lib/isccc/include/isccc/result.h b/lib/isccc/include/isccc/result.h
|
||||
index 6c79dd7..a85861c 100644
|
||||
--- a/lib/isccc/include/isccc/result.h
|
||||
+++ b/lib/isccc/include/isccc/result.h
|
||||
@@ -47,8 +47,10 @@
|
||||
#define ISCCC_R_CLOCKSKEW (ISC_RESULTCLASS_ISCCC + 4)
|
||||
/*% Duplicate */
|
||||
#define ISCCC_R_DUPLICATE (ISC_RESULTCLASS_ISCCC + 5)
|
||||
+/*% Maximum recursion depth */
|
||||
+#define ISCCC_R_MAXDEPTH (ISC_RESULTCLASS_ISCCC + 6)
|
||||
|
||||
-#define ISCCC_R_NRESULTS 6 /*%< Number of results */
|
||||
+#define ISCCC_R_NRESULTS 7 /*%< Number of results */
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
diff --git a/lib/isccc/result.c b/lib/isccc/result.c
|
||||
index 8419bbb..325200b 100644
|
||||
--- a/lib/isccc/result.c
|
||||
+++ b/lib/isccc/result.c
|
||||
@@ -40,7 +40,8 @@ static const char *text[ISCCC_R_NRESULTS] = {
|
||||
"bad auth", /* 3 */
|
||||
"expired", /* 4 */
|
||||
"clock skew", /* 5 */
|
||||
- "duplicate" /* 6 */
|
||||
+ "duplicate", /* 6 */
|
||||
+ "max depth", /* 7 */
|
||||
};
|
||||
|
||||
static const char *ids[ISCCC_R_NRESULTS] = {
|
||||
@@ -50,6 +51,7 @@ static const char *ids[ISCCC_R_NRESULTS] = {
|
||||
"ISCCC_R_EXPIRED",
|
||||
"ISCCC_R_CLOCKSKEW",
|
||||
"ISCCC_R_DUPLICATE",
|
||||
+ "ISCCC_R_MAXDEPTH",
|
||||
};
|
||||
|
||||
#define ISCCC_RESULT_RESULTSET 2
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -22,6 +22,8 @@ SRC_URI = "https://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.gz \
|
||||
file://CVE-2022-2795.patch \
|
||||
file://CVE-2022-38177.patch \
|
||||
file://CVE-2022-38178.patch \
|
||||
file://CVE-2023-2828.patch \
|
||||
file://CVE-2023-3341.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "0d8efbe7ec166ada90e46add4267b7e7c934790cba9bd5af6b8380a4fbfb5aff"
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
From 703418fe9d2e3b1e8d594df5788d8001a8116265 Mon Sep 17 00:00:00 2001
|
||||
From: Jeffrey Bencteux <jeffbencteux@gmail.com>
|
||||
Date: Fri, 30 Jun 2023 19:02:45 +0200
|
||||
Subject: [PATCH] CVE-2023-40303: ftpd,rcp,rlogin,rsh,rshd,uucpd: fix: check
|
||||
set*id() return values
|
||||
|
||||
Several setuid(), setgid(), seteuid() and setguid() return values
|
||||
were not checked in ftpd/rcp/rlogin/rsh/rshd/uucpd code potentially
|
||||
leading to potential security issues.
|
||||
|
||||
CVE: CVE-2023-40303
|
||||
Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=e4e65c03f4c11292a3e40ef72ca3f194c8bffdd6]
|
||||
Signed-off-by: Jeffrey Bencteux <jeffbencteux@gmail.com>
|
||||
Signed-off-by: Simon Josefsson <simon@josefsson.org>
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
ftpd/ftpd.c | 10 +++++++---
|
||||
src/rcp.c | 39 +++++++++++++++++++++++++++++++++------
|
||||
src/rlogin.c | 11 +++++++++--
|
||||
src/rsh.c | 25 +++++++++++++++++++++----
|
||||
src/rshd.c | 20 +++++++++++++++++---
|
||||
src/uucpd.c | 15 +++++++++++++--
|
||||
6 files changed, 100 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/ftpd/ftpd.c b/ftpd/ftpd.c
|
||||
index 5db88d0..b52b122 100644
|
||||
--- a/ftpd/ftpd.c
|
||||
+++ b/ftpd/ftpd.c
|
||||
@@ -862,7 +862,9 @@ end_login (struct credentials *pcred)
|
||||
char *remotehost = pcred->remotehost;
|
||||
int atype = pcred->auth_type;
|
||||
|
||||
- seteuid ((uid_t) 0);
|
||||
+ if (seteuid ((uid_t) 0) == -1)
|
||||
+ _exit (EXIT_FAILURE);
|
||||
+
|
||||
if (pcred->logged_in)
|
||||
{
|
||||
logwtmp_keep_open (ttyline, "", "");
|
||||
@@ -1151,7 +1153,8 @@ getdatasock (const char *mode)
|
||||
|
||||
if (data >= 0)
|
||||
return fdopen (data, mode);
|
||||
- seteuid ((uid_t) 0);
|
||||
+ if (seteuid ((uid_t) 0) == -1)
|
||||
+ _exit (EXIT_FAILURE);
|
||||
s = socket (ctrl_addr.ss_family, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
goto bad;
|
||||
@@ -1978,7 +1981,8 @@ passive (int epsv, int af)
|
||||
else /* !AF_INET6 */
|
||||
((struct sockaddr_in *) &pasv_addr)->sin_port = 0;
|
||||
|
||||
- seteuid ((uid_t) 0);
|
||||
+ if (seteuid ((uid_t) 0) == -1)
|
||||
+ _exit (EXIT_FAILURE);
|
||||
if (bind (pdata, (struct sockaddr *) &pasv_addr, pasv_addrlen) < 0)
|
||||
{
|
||||
if (seteuid ((uid_t) cred.uid))
|
||||
diff --git a/src/rcp.c b/src/rcp.c
|
||||
index bafa35f..366295c 100644
|
||||
--- a/src/rcp.c
|
||||
+++ b/src/rcp.c
|
||||
@@ -347,14 +347,23 @@ main (int argc, char *argv[])
|
||||
if (from_option)
|
||||
{ /* Follow "protocol", send data. */
|
||||
response ();
|
||||
- setuid (userid);
|
||||
+
|
||||
+ if (setuid (userid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
+
|
||||
source (argc, argv);
|
||||
exit (errs);
|
||||
}
|
||||
|
||||
if (to_option)
|
||||
{ /* Receive data. */
|
||||
- setuid (userid);
|
||||
+ if (setuid (userid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
+
|
||||
sink (argc, argv);
|
||||
exit (errs);
|
||||
}
|
||||
@@ -539,7 +548,11 @@ toremote (char *targ, int argc, char *argv[])
|
||||
if (response () < 0)
|
||||
exit (EXIT_FAILURE);
|
||||
free (bp);
|
||||
- setuid (userid);
|
||||
+
|
||||
+ if (setuid (userid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
}
|
||||
source (1, argv + i);
|
||||
close (rem);
|
||||
@@ -634,7 +647,12 @@ tolocal (int argc, char *argv[])
|
||||
++errs;
|
||||
continue;
|
||||
}
|
||||
- seteuid (userid);
|
||||
+
|
||||
+ if (seteuid (userid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
+
|
||||
#if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
|
||||
sslen = sizeof (ss);
|
||||
(void) getpeername (rem, (struct sockaddr *) &ss, &sslen);
|
||||
@@ -647,7 +665,12 @@ tolocal (int argc, char *argv[])
|
||||
#endif
|
||||
vect[0] = target;
|
||||
sink (1, vect);
|
||||
- seteuid (effuid);
|
||||
+
|
||||
+ if (seteuid (effuid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
+
|
||||
close (rem);
|
||||
rem = -1;
|
||||
#ifdef SHISHI
|
||||
@@ -1453,7 +1476,11 @@ susystem (char *s, int userid)
|
||||
return (127);
|
||||
|
||||
case 0:
|
||||
- setuid (userid);
|
||||
+ if (setuid (userid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
+
|
||||
execl (PATH_BSHELL, "sh", "-c", s, NULL);
|
||||
_exit (127);
|
||||
}
|
||||
diff --git a/src/rlogin.c b/src/rlogin.c
|
||||
index e5e11a7..6b38901 100644
|
||||
--- a/src/rlogin.c
|
||||
+++ b/src/rlogin.c
|
||||
@@ -649,8 +649,15 @@ try_connect:
|
||||
/* Now change to the real user ID. We have to be set-user-ID root
|
||||
to get the privileged port that rcmd () uses. We now want, however,
|
||||
to run as the real user who invoked us. */
|
||||
- seteuid (uid);
|
||||
- setuid (uid);
|
||||
+ if (seteuid (uid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
+
|
||||
+ if (setuid (uid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
|
||||
doit (&osmask); /* The old mask will activate SIGURG and SIGUSR1! */
|
||||
|
||||
diff --git a/src/rsh.c b/src/rsh.c
|
||||
index bd70372..b451a70 100644
|
||||
--- a/src/rsh.c
|
||||
+++ b/src/rsh.c
|
||||
@@ -278,8 +278,17 @@ main (int argc, char **argv)
|
||||
{
|
||||
if (asrsh)
|
||||
*argv = (char *) "rlogin";
|
||||
- seteuid (getuid ());
|
||||
- setuid (getuid ());
|
||||
+
|
||||
+ if (seteuid (getuid ()) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
+ }
|
||||
+
|
||||
+ if (setuid (getuid ()) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
+ }
|
||||
+
|
||||
execv (PATH_RLOGIN, argv);
|
||||
error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN);
|
||||
}
|
||||
@@ -543,8 +552,16 @@ try_connect:
|
||||
error (0, errno, "setsockopt DEBUG (ignored)");
|
||||
}
|
||||
|
||||
- seteuid (uid);
|
||||
- setuid (uid);
|
||||
+ if (seteuid (uid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
+ }
|
||||
+
|
||||
+ if (setuid (uid) == -1)
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
+ }
|
||||
+
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigemptyset (&sigs);
|
||||
sigaddset (&sigs, SIGINT);
|
||||
diff --git a/src/rshd.c b/src/rshd.c
|
||||
index b824a10..8cdcd06 100644
|
||||
--- a/src/rshd.c
|
||||
+++ b/src/rshd.c
|
||||
@@ -1848,8 +1848,18 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
|
||||
pwd->pw_shell = PATH_BSHELL;
|
||||
|
||||
/* Set the gid, then uid to become the user specified by "locuser" */
|
||||
- setegid ((gid_t) pwd->pw_gid);
|
||||
- setgid ((gid_t) pwd->pw_gid);
|
||||
+ if (setegid ((gid_t) pwd->pw_gid) == -1)
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setegid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
+ if (setgid ((gid_t) pwd->pw_gid) == -1)
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setgid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
+
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */
|
||||
#endif
|
||||
@@ -1871,7 +1881,11 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
|
||||
}
|
||||
#endif /* WITH_PAM */
|
||||
|
||||
- setuid ((uid_t) pwd->pw_uid);
|
||||
+ if (setuid ((uid_t) pwd->pw_uid) == -1)
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setuid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
|
||||
/* We'll execute the client's command in the home directory
|
||||
* of locuser. Note, that the chdir must be executed after
|
||||
diff --git a/src/uucpd.c b/src/uucpd.c
|
||||
index 55c3d44..6aba294 100644
|
||||
--- a/src/uucpd.c
|
||||
+++ b/src/uucpd.c
|
||||
@@ -254,7 +254,12 @@ doit (struct sockaddr *sap, socklen_t salen)
|
||||
sprintf (Username, "USER=%s", user);
|
||||
sprintf (Logname, "LOGNAME=%s", user);
|
||||
dologin (pw, sap, salen);
|
||||
- setgid (pw->pw_gid);
|
||||
+
|
||||
+ if (setgid (pw->pw_gid) == -1)
|
||||
+ {
|
||||
+ fprintf (stderr, "setgid() failed");
|
||||
+ return;
|
||||
+ }
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups (pw->pw_name, pw->pw_gid);
|
||||
#endif
|
||||
@@ -263,7 +268,13 @@ doit (struct sockaddr *sap, socklen_t salen)
|
||||
fprintf (stderr, "Login incorrect.");
|
||||
return;
|
||||
}
|
||||
- setuid (pw->pw_uid);
|
||||
+
|
||||
+ if (setuid (pw->pw_uid) == -1)
|
||||
+ {
|
||||
+ fprintf (stderr, "setuid() failed");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
execl (uucico_location, "uucico", NULL);
|
||||
perror ("uucico server: execl");
|
||||
}
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
From 70fe022f9dac760eaece0228cad17e3d29a57fb8 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Josefsson <simon@josefsson.org>
|
||||
Date: Mon, 31 Jul 2023 13:59:05 +0200
|
||||
Subject: [PATCH] CVE-2023-40303: Indent changes in previous commit.
|
||||
|
||||
CVE: CVE-2023-40303
|
||||
Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=9122999252c7e21eb7774de11d539748e7bdf46d]
|
||||
Signed-off-by: Khem Raj <raj.khem@gmail.com>
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
src/rcp.c | 42 ++++++++++++++++++++++++------------------
|
||||
src/rlogin.c | 12 ++++++------
|
||||
src/rsh.c | 24 ++++++++++++------------
|
||||
src/rshd.c | 24 ++++++++++++------------
|
||||
src/uucpd.c | 16 ++++++++--------
|
||||
5 files changed, 62 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/src/rcp.c b/src/rcp.c
|
||||
index cdcf8500..652f22e6 100644
|
||||
--- a/src/rcp.c
|
||||
+++ b/src/rcp.c
|
||||
@@ -347,9 +347,10 @@ main (int argc, char *argv[])
|
||||
response ();
|
||||
|
||||
if (setuid (userid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
|
||||
source (argc, argv);
|
||||
exit (errs);
|
||||
@@ -358,9 +359,10 @@ main (int argc, char *argv[])
|
||||
if (to_option)
|
||||
{ /* Receive data. */
|
||||
if (setuid (userid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
|
||||
sink (argc, argv);
|
||||
exit (errs);
|
||||
@@ -548,9 +550,10 @@ toremote (char *targ, int argc, char *argv[])
|
||||
free (bp);
|
||||
|
||||
if (setuid (userid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
}
|
||||
source (1, argv + i);
|
||||
close (rem);
|
||||
@@ -645,9 +648,10 @@ tolocal (int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (seteuid (userid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
|
||||
#if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
|
||||
sslen = sizeof (ss);
|
||||
@@ -663,9 +667,10 @@ tolocal (int argc, char *argv[])
|
||||
sink (1, vect);
|
||||
|
||||
if (seteuid (effuid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
|
||||
close (rem);
|
||||
rem = -1;
|
||||
@@ -1465,9 +1470,10 @@ susystem (char *s, int userid)
|
||||
|
||||
case 0:
|
||||
if (setuid (userid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0,
|
||||
+ "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
|
||||
execl (PATH_BSHELL, "sh", "-c", s, NULL);
|
||||
_exit (127);
|
||||
diff --git a/src/rlogin.c b/src/rlogin.c
|
||||
index c543de0c..4360202f 100644
|
||||
--- a/src/rlogin.c
|
||||
+++ b/src/rlogin.c
|
||||
@@ -648,14 +648,14 @@ try_connect:
|
||||
to get the privileged port that rcmd () uses. We now want, however,
|
||||
to run as the real user who invoked us. */
|
||||
if (seteuid (uid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)");
|
||||
+ }
|
||||
|
||||
if (setuid (uid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)");
|
||||
+ }
|
||||
|
||||
doit (&osmask); /* The old mask will activate SIGURG and SIGUSR1! */
|
||||
|
||||
diff --git a/src/rsh.c b/src/rsh.c
|
||||
index 6f60667d..179b47cd 100644
|
||||
--- a/src/rsh.c
|
||||
+++ b/src/rsh.c
|
||||
@@ -278,14 +278,14 @@ main (int argc, char **argv)
|
||||
*argv = (char *) "rlogin";
|
||||
|
||||
if (seteuid (getuid ()) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
+ }
|
||||
|
||||
if (setuid (getuid ()) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
+ }
|
||||
|
||||
execv (PATH_RLOGIN, argv);
|
||||
error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN);
|
||||
@@ -551,14 +551,14 @@ try_connect:
|
||||
}
|
||||
|
||||
if (seteuid (uid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "seteuid() failed");
|
||||
+ }
|
||||
|
||||
if (setuid (uid) == -1)
|
||||
- {
|
||||
- error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
- }
|
||||
+ {
|
||||
+ error (EXIT_FAILURE, errno, "setuid() failed");
|
||||
+ }
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
sigemptyset (&sigs);
|
||||
diff --git a/src/rshd.c b/src/rshd.c
|
||||
index 707790e7..3a153a18 100644
|
||||
--- a/src/rshd.c
|
||||
+++ b/src/rshd.c
|
||||
@@ -1848,16 +1848,16 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
|
||||
|
||||
/* Set the gid, then uid to become the user specified by "locuser" */
|
||||
if (setegid ((gid_t) pwd->pw_gid) == -1)
|
||||
- {
|
||||
- rshd_error ("Cannot drop privileges (setegid() failed)\n");
|
||||
- exit (EXIT_FAILURE);
|
||||
- }
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setegid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
|
||||
if (setgid ((gid_t) pwd->pw_gid) == -1)
|
||||
- {
|
||||
- rshd_error ("Cannot drop privileges (setgid() failed)\n");
|
||||
- exit (EXIT_FAILURE);
|
||||
- }
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setgid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */
|
||||
@@ -1881,10 +1881,10 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen)
|
||||
#endif /* WITH_PAM */
|
||||
|
||||
if (setuid ((uid_t) pwd->pw_uid) == -1)
|
||||
- {
|
||||
- rshd_error ("Cannot drop privileges (setuid() failed)\n");
|
||||
- exit (EXIT_FAILURE);
|
||||
- }
|
||||
+ {
|
||||
+ rshd_error ("Cannot drop privileges (setuid() failed)\n");
|
||||
+ exit (EXIT_FAILURE);
|
||||
+ }
|
||||
|
||||
/* We'll execute the client's command in the home directory
|
||||
* of locuser. Note, that the chdir must be executed after
|
||||
diff --git a/src/uucpd.c b/src/uucpd.c
|
||||
index 29cfce35..fde7b9c9 100644
|
||||
--- a/src/uucpd.c
|
||||
+++ b/src/uucpd.c
|
||||
@@ -254,10 +254,10 @@ doit (struct sockaddr *sap, socklen_t salen)
|
||||
dologin (pw, sap, salen);
|
||||
|
||||
if (setgid (pw->pw_gid) == -1)
|
||||
- {
|
||||
- fprintf (stderr, "setgid() failed");
|
||||
- return;
|
||||
- }
|
||||
+ {
|
||||
+ fprintf (stderr, "setgid() failed");
|
||||
+ return;
|
||||
+ }
|
||||
#ifdef HAVE_INITGROUPS
|
||||
initgroups (pw->pw_name, pw->pw_gid);
|
||||
#endif
|
||||
@@ -268,10 +268,10 @@ doit (struct sockaddr *sap, socklen_t salen)
|
||||
}
|
||||
|
||||
if (setuid (pw->pw_uid) == -1)
|
||||
- {
|
||||
- fprintf (stderr, "setuid() failed");
|
||||
- return;
|
||||
- }
|
||||
+ {
|
||||
+ fprintf (stderr, "setuid() failed");
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
execl (uucico_location, "uucico", NULL);
|
||||
perror ("uucico server: execl");
|
||||
@@ -25,6 +25,8 @@ SRC_URI = "${GNU_MIRROR}/inetutils/inetutils-${PV}.tar.gz \
|
||||
file://fix-buffer-fortify-tfpt.patch \
|
||||
file://CVE-2021-40491.patch \
|
||||
file://CVE-2022-39028.patch \
|
||||
file://0001-CVE-2023-40303-ftpd-rcp-rlogin-rsh-rshd-uucpd-fix-ch.patch \
|
||||
file://0002-CVE-2023-40303-Indent-changes-in-previous-commit.patch \
|
||||
"
|
||||
|
||||
SRC_URI[md5sum] = "04852c26c47cc8c6b825f2b74f191f52"
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
From f6213e03887237714eb5bcfc9089c707069f87c5 Mon Sep 17 00:00:00 2001
|
||||
From: Damien Miller <djm@mindrot.org>
|
||||
Date: Fri, 1 Oct 2021 16:35:49 +1000
|
||||
Subject: [PATCH 01/12] make OPENSSL_HAS_ECC checks more thorough
|
||||
|
||||
ok dtucker
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/dee22129bbc61e25b1003adfa2bc584c5406ef2d]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-pkcs11-client.c | 16 ++++++++--------
|
||||
ssh-pkcs11.c | 26 +++++++++++++-------------
|
||||
2 files changed, 21 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
|
||||
index 8a0ffef..41114c7 100644
|
||||
--- a/ssh-pkcs11-client.c
|
||||
+++ b/ssh-pkcs11-client.c
|
||||
@@ -163,7 +163,7 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
static ECDSA_SIG *
|
||||
ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
const BIGNUM *rp, EC_KEY *ec)
|
||||
@@ -220,12 +220,12 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
sshbuf_free(msg);
|
||||
return (ret);
|
||||
}
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
static RSA_METHOD *helper_rsa;
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
static EC_KEY_METHOD *helper_ecdsa;
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
/* redirect private key crypto operations to the ssh-pkcs11-helper */
|
||||
static void
|
||||
@@ -233,10 +233,10 @@ wrap_key(struct sshkey *k)
|
||||
{
|
||||
if (k->type == KEY_RSA)
|
||||
RSA_set_method(k->rsa, helper_rsa);
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
else if (k->type == KEY_ECDSA)
|
||||
EC_KEY_set_method(k->ecdsa, helper_ecdsa);
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
else
|
||||
fatal("%s: unknown key type", __func__);
|
||||
}
|
||||
@@ -247,7 +247,7 @@ pkcs11_start_helper_methods(void)
|
||||
if (helper_rsa != NULL)
|
||||
return (0);
|
||||
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
|
||||
unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
|
||||
if (helper_ecdsa != NULL)
|
||||
@@ -257,7 +257,7 @@ pkcs11_start_helper_methods(void)
|
||||
return (-1);
|
||||
EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
|
||||
EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
|
||||
fatal("%s: RSA_meth_dup failed", __func__);
|
||||
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
|
||||
index a302c79..b56a41b 100644
|
||||
--- a/ssh-pkcs11.c
|
||||
+++ b/ssh-pkcs11.c
|
||||
@@ -78,7 +78,7 @@ struct pkcs11_key {
|
||||
|
||||
int pkcs11_interactive = 0;
|
||||
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
static void
|
||||
ossl_error(const char *msg)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ ossl_error(const char *msg)
|
||||
error("%s: libcrypto error: %.100s", __func__,
|
||||
ERR_error_string(e, NULL));
|
||||
}
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
int
|
||||
pkcs11_init(int interactive)
|
||||
@@ -190,10 +190,10 @@ pkcs11_del_provider(char *provider_id)
|
||||
|
||||
static RSA_METHOD *rsa_method;
|
||||
static int rsa_idx = 0;
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
static EC_KEY_METHOD *ec_key_method;
|
||||
static int ec_key_idx = 0;
|
||||
-#endif
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
/* release a wrapped object */
|
||||
static void
|
||||
@@ -492,7 +492,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
||||
return (0);
|
||||
}
|
||||
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
/* openssl callback doing the actual signing operation */
|
||||
static ECDSA_SIG *
|
||||
ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
@@ -604,7 +604,7 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
|
||||
|
||||
return (0);
|
||||
}
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
/* remove trailing spaces */
|
||||
static void
|
||||
@@ -679,7 +679,7 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
|
||||
return (0);
|
||||
}
|
||||
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
static struct sshkey *
|
||||
pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
CK_OBJECT_HANDLE *obj)
|
||||
@@ -802,7 +802,7 @@ fail:
|
||||
|
||||
return (key);
|
||||
}
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
static struct sshkey *
|
||||
pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
@@ -910,7 +910,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
#endif
|
||||
struct sshkey *key = NULL;
|
||||
int i;
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
int nid;
|
||||
#endif
|
||||
const u_char *cp;
|
||||
@@ -999,7 +999,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
key->type = KEY_RSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
rsa = NULL; /* now owned by key */
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
} else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
|
||||
if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
|
||||
error("invalid x509; no ec key");
|
||||
@@ -1030,7 +1030,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
key->type = KEY_ECDSA;
|
||||
key->flags |= SSHKEY_FLAG_EXT;
|
||||
ec = NULL; /* now owned by key */
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
} else {
|
||||
error("unknown certificate key type");
|
||||
goto out;
|
||||
@@ -1237,11 +1237,11 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
|
||||
case CKK_RSA:
|
||||
key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
|
||||
break;
|
||||
-#ifdef HAVE_EC_KEY_METHOD_NEW
|
||||
+#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
case CKK_ECDSA:
|
||||
key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
|
||||
break;
|
||||
-#endif /* HAVE_EC_KEY_METHOD_NEW */
|
||||
+#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
default:
|
||||
/* XXX print key type? */
|
||||
key = NULL;
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,581 @@
|
||||
From 92cebfbcc221c9ef3f6bbb78da3d7699c0ae56be Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Wed, 19 Jul 2023 14:03:45 +0000
|
||||
Subject: [PATCH 02/12] upstream: Separate ssh-pkcs11-helpers for each p11
|
||||
module
|
||||
|
||||
Make ssh-pkcs11-client start an independent helper for each provider,
|
||||
providing better isolation between modules and reliability if a single
|
||||
module misbehaves.
|
||||
|
||||
This also implements reference counting of PKCS#11-hosted keys,
|
||||
allowing ssh-pkcs11-helper subprocesses to be automatically reaped
|
||||
when no remaining keys reference them. This fixes some bugs we have
|
||||
that make PKCS11 keys unusable after they have been deleted, e.g.
|
||||
https://bugzilla.mindrot.org/show_bug.cgi?id=3125
|
||||
|
||||
ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/099cdf59ce1e72f55d421c8445bf6321b3004755]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-pkcs11-client.c | 372 +++++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 282 insertions(+), 90 deletions(-)
|
||||
|
||||
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
|
||||
index 41114c7..4f3c6ed 100644
|
||||
--- a/ssh-pkcs11-client.c
|
||||
+++ b/ssh-pkcs11-client.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2010 Markus Friedl. All rights reserved.
|
||||
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
|
||||
@@ -30,12 +30,11 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
+#include <limits.h>
|
||||
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
-#include "openbsd-compat/openssl-compat.h"
|
||||
-
|
||||
#include "pathnames.h"
|
||||
#include "xmalloc.h"
|
||||
#include "sshbuf.h"
|
||||
@@ -47,18 +46,140 @@
|
||||
#include "ssh-pkcs11.h"
|
||||
#include "ssherr.h"
|
||||
|
||||
+#include "openbsd-compat/openssl-compat.h"
|
||||
+
|
||||
/* borrows code from sftp-server and ssh-agent */
|
||||
|
||||
-static int fd = -1;
|
||||
-static pid_t pid = -1;
|
||||
+/*
|
||||
+ * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up
|
||||
+ * by provider path or their unique EC/RSA METHOD pointers.
|
||||
+ */
|
||||
+struct helper {
|
||||
+ char *path;
|
||||
+ pid_t pid;
|
||||
+ int fd;
|
||||
+ RSA_METHOD *rsa_meth;
|
||||
+ EC_KEY_METHOD *ec_meth;
|
||||
+ int (*rsa_finish)(RSA *rsa);
|
||||
+ void (*ec_finish)(EC_KEY *key);
|
||||
+ size_t nrsa, nec; /* number of active keys of each type */
|
||||
+};
|
||||
+static struct helper **helpers;
|
||||
+static size_t nhelpers;
|
||||
+
|
||||
+static struct helper *
|
||||
+helper_by_provider(const char *path)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ for (i = 0; i < nhelpers; i++) {
|
||||
+ if (helpers[i] == NULL || helpers[i]->path == NULL ||
|
||||
+ helpers[i]->fd == -1)
|
||||
+ continue;
|
||||
+ if (strcmp(helpers[i]->path, path) == 0)
|
||||
+ return helpers[i];
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static struct helper *
|
||||
+helper_by_rsa(const RSA *rsa)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ const RSA_METHOD *meth;
|
||||
+
|
||||
+ if ((meth = RSA_get_method(rsa)) == NULL)
|
||||
+ return NULL;
|
||||
+ for (i = 0; i < nhelpers; i++) {
|
||||
+ if (helpers[i] != NULL && helpers[i]->rsa_meth == meth)
|
||||
+ return helpers[i];
|
||||
+ }
|
||||
+ return NULL;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static struct helper *
|
||||
+helper_by_ec(const EC_KEY *ec)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ const EC_KEY_METHOD *meth;
|
||||
+
|
||||
+ if ((meth = EC_KEY_get_method(ec)) == NULL)
|
||||
+ return NULL;
|
||||
+ for (i = 0; i < nhelpers; i++) {
|
||||
+ if (helpers[i] != NULL && helpers[i]->ec_meth == meth)
|
||||
+ return helpers[i];
|
||||
+ }
|
||||
+ return NULL;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+helper_free(struct helper *helper)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ int found = 0;
|
||||
+
|
||||
+ if (helper == NULL)
|
||||
+ return;
|
||||
+ if (helper->path == NULL || helper->ec_meth == NULL ||
|
||||
+ helper->rsa_meth == NULL)
|
||||
+ fatal("%s: inconsistent helper", __func__);
|
||||
+ debug3("%s: free helper for provider %s", __func__ , helper->path);
|
||||
+ for (i = 0; i < nhelpers; i++) {
|
||||
+ if (helpers[i] == helper) {
|
||||
+ if (found)
|
||||
+ fatal("%s: helper recorded more than once", __func__);
|
||||
+ found = 1;
|
||||
+ }
|
||||
+ else if (found)
|
||||
+ helpers[i - 1] = helpers[i];
|
||||
+ }
|
||||
+ if (found) {
|
||||
+ helpers = xrecallocarray(helpers, nhelpers,
|
||||
+ nhelpers - 1, sizeof(*helpers));
|
||||
+ nhelpers--;
|
||||
+ }
|
||||
+ free(helper->path);
|
||||
+ EC_KEY_METHOD_free(helper->ec_meth);
|
||||
+ RSA_meth_free(helper->rsa_meth);
|
||||
+ free(helper);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+helper_terminate(struct helper *helper)
|
||||
+{
|
||||
+ if (helper == NULL) {
|
||||
+ return;
|
||||
+ } else if (helper->fd == -1) {
|
||||
+ debug3("%s: already terminated", __func__);
|
||||
+ } else {
|
||||
+ debug3("terminating helper for %s; "
|
||||
+ "remaining %zu RSA %zu ECDSA", __func__,
|
||||
+ helper->path, helper->nrsa, helper->nec);
|
||||
+ close(helper->fd);
|
||||
+ /* XXX waitpid() */
|
||||
+ helper->fd = -1;
|
||||
+ helper->pid = -1;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Don't delete the helper entry until there are no remaining keys
|
||||
+ * that reference it. Otherwise, any signing operation would call
|
||||
+ * a free'd METHOD pointer and that would be bad.
|
||||
+ */
|
||||
+ if (helper->nrsa == 0 && helper->nec == 0)
|
||||
+ helper_free(helper);
|
||||
+}
|
||||
|
||||
static void
|
||||
-send_msg(struct sshbuf *m)
|
||||
+send_msg(int fd, struct sshbuf *m)
|
||||
{
|
||||
u_char buf[4];
|
||||
size_t mlen = sshbuf_len(m);
|
||||
int r;
|
||||
|
||||
+ if (fd == -1)
|
||||
+ return;
|
||||
POKE_U32(buf, mlen);
|
||||
if (atomicio(vwrite, fd, buf, 4) != 4 ||
|
||||
atomicio(vwrite, fd, sshbuf_mutable_ptr(m),
|
||||
@@ -69,12 +190,15 @@ send_msg(struct sshbuf *m)
|
||||
}
|
||||
|
||||
static int
|
||||
-recv_msg(struct sshbuf *m)
|
||||
+recv_msg(int fd, struct sshbuf *m)
|
||||
{
|
||||
u_int l, len;
|
||||
u_char c, buf[1024];
|
||||
int r;
|
||||
|
||||
+ sshbuf_reset(m);
|
||||
+ if (fd == -1)
|
||||
+ return 0; /* XXX */
|
||||
if ((len = atomicio(read, fd, buf, 4)) != 4) {
|
||||
error("read from helper failed: %u", len);
|
||||
return (0); /* XXX */
|
||||
@@ -83,7 +207,6 @@ recv_msg(struct sshbuf *m)
|
||||
if (len > 256 * 1024)
|
||||
fatal("response too long: %u", len);
|
||||
/* read len bytes into m */
|
||||
- sshbuf_reset(m);
|
||||
while (len > 0) {
|
||||
l = len;
|
||||
if (l > sizeof(buf))
|
||||
@@ -104,14 +227,17 @@ recv_msg(struct sshbuf *m)
|
||||
int
|
||||
pkcs11_init(int interactive)
|
||||
{
|
||||
- return (0);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
void
|
||||
pkcs11_terminate(void)
|
||||
{
|
||||
- if (fd >= 0)
|
||||
- close(fd);
|
||||
+ size_t i;
|
||||
+
|
||||
+ debug3("%s: terminating %zu helpers", __func__, nhelpers);
|
||||
+ for (i = 0; i < nhelpers; i++)
|
||||
+ helper_terminate(helpers[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -122,7 +248,11 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
|
||||
u_char *blob = NULL, *signature = NULL;
|
||||
size_t blen, slen = 0;
|
||||
int r, ret = -1;
|
||||
+ struct helper *helper;
|
||||
|
||||
+ if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1)
|
||||
+ fatal("%s: no helper for PKCS11 key", __func__);
|
||||
+ debug3("%s: signing with PKCS11 provider %s", __func__, helper->path);
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
goto fail;
|
||||
key = sshkey_new(KEY_UNSPEC);
|
||||
@@ -144,10 +274,10 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
|
||||
(r = sshbuf_put_string(msg, from, flen)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, 0)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
- send_msg(msg);
|
||||
+ send_msg(helper->fd, msg);
|
||||
sshbuf_reset(msg);
|
||||
|
||||
- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||
+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
if (slen <= (size_t)RSA_size(rsa)) {
|
||||
@@ -163,7 +293,26 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
+static int
|
||||
+rsa_finish(RSA *rsa)
|
||||
+{
|
||||
+ struct helper *helper;
|
||||
+
|
||||
+ if ((helper = helper_by_rsa(rsa)) == NULL)
|
||||
+ fatal("%s: no helper for PKCS11 key", __func__);
|
||||
+ debug3("%s: free PKCS11 RSA key for provider %s", __func__, helper->path);
|
||||
+ if (helper->rsa_finish != NULL)
|
||||
+ helper->rsa_finish(rsa);
|
||||
+ if (helper->nrsa == 0)
|
||||
+ fatal("%s: RSA refcount error", __func__);
|
||||
+ helper->nrsa--;
|
||||
+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
|
||||
+ helper->path, helper->nrsa, helper->nec);
|
||||
+ if (helper->nrsa == 0 && helper->nec == 0)
|
||||
+ helper_terminate(helper);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static ECDSA_SIG *
|
||||
ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
const BIGNUM *rp, EC_KEY *ec)
|
||||
@@ -175,7 +324,11 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
u_char *blob = NULL, *signature = NULL;
|
||||
size_t blen, slen = 0;
|
||||
int r, nid;
|
||||
+ struct helper *helper;
|
||||
|
||||
+ if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1)
|
||||
+ fatal("%s: no helper for PKCS11 key", __func__);
|
||||
+ debug3("%s: signing with PKCS11 provider %s", __func__, helper->path);
|
||||
nid = sshkey_ecdsa_key_to_nid(ec);
|
||||
if (nid < 0) {
|
||||
error("%s: couldn't get curve nid", __func__);
|
||||
@@ -203,10 +356,10 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
(r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
|
||||
(r = sshbuf_put_u32(msg, 0)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
- send_msg(msg);
|
||||
+ send_msg(helper->fd, msg);
|
||||
sshbuf_reset(msg);
|
||||
|
||||
- if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||
+ if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) {
|
||||
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
cp = signature;
|
||||
@@ -220,75 +373,110 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
|
||||
sshbuf_free(msg);
|
||||
return (ret);
|
||||
}
|
||||
-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
|
||||
-static RSA_METHOD *helper_rsa;
|
||||
-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
-static EC_KEY_METHOD *helper_ecdsa;
|
||||
-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
+static void
|
||||
+ecdsa_do_finish(EC_KEY *ec)
|
||||
+{
|
||||
+ struct helper *helper;
|
||||
+
|
||||
+ if ((helper = helper_by_ec(ec)) == NULL)
|
||||
+ fatal("%s: no helper for PKCS11 key", __func__);
|
||||
+ debug3("%s: free PKCS11 ECDSA key for provider %s", __func__, helper->path);
|
||||
+ if (helper->ec_finish != NULL)
|
||||
+ helper->ec_finish(ec);
|
||||
+ if (helper->nec == 0)
|
||||
+ fatal("%s: ECDSA refcount error", __func__);
|
||||
+ helper->nec--;
|
||||
+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
|
||||
+ helper->path, helper->nrsa, helper->nec);
|
||||
+ if (helper->nrsa == 0 && helper->nec == 0)
|
||||
+ helper_terminate(helper);
|
||||
+}
|
||||
|
||||
/* redirect private key crypto operations to the ssh-pkcs11-helper */
|
||||
static void
|
||||
-wrap_key(struct sshkey *k)
|
||||
+wrap_key(struct helper *helper, struct sshkey *k)
|
||||
{
|
||||
- if (k->type == KEY_RSA)
|
||||
- RSA_set_method(k->rsa, helper_rsa);
|
||||
-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
- else if (k->type == KEY_ECDSA)
|
||||
- EC_KEY_set_method(k->ecdsa, helper_ecdsa);
|
||||
-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
- else
|
||||
+ debug3("%s: wrap %s for provider %s", __func__, sshkey_type(k), helper->path);
|
||||
+ if (k->type == KEY_RSA) {
|
||||
+ RSA_set_method(k->rsa, helper->rsa_meth);
|
||||
+ if (helper->nrsa++ >= INT_MAX)
|
||||
+ fatal("%s: RSA refcount error", __func__);
|
||||
+ } else if (k->type == KEY_ECDSA) {
|
||||
+ EC_KEY_set_method(k->ecdsa, helper->ec_meth);
|
||||
+ if (helper->nec++ >= INT_MAX)
|
||||
+ fatal("%s: EC refcount error", __func__);
|
||||
+ } else
|
||||
fatal("%s: unknown key type", __func__);
|
||||
+ k->flags |= SSHKEY_FLAG_EXT;
|
||||
+ debug3("%s: provider %s remaining keys: %zu RSA %zu ECDSA", __func__,
|
||||
+ helper->path, helper->nrsa, helper->nec);
|
||||
}
|
||||
|
||||
static int
|
||||
-pkcs11_start_helper_methods(void)
|
||||
+pkcs11_start_helper_methods(struct helper *helper)
|
||||
{
|
||||
- if (helper_rsa != NULL)
|
||||
- return (0);
|
||||
-
|
||||
-#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
|
||||
- int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
|
||||
+ int (*ec_init)(EC_KEY *key);
|
||||
+ int (*ec_copy)(EC_KEY *dest, const EC_KEY *src);
|
||||
+ int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp);
|
||||
+ int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key);
|
||||
+ int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key);
|
||||
+ int (*ec_sign)(int, const unsigned char *, int, unsigned char *,
|
||||
unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
|
||||
- if (helper_ecdsa != NULL)
|
||||
- return (0);
|
||||
- helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
|
||||
- if (helper_ecdsa == NULL)
|
||||
- return (-1);
|
||||
- EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL);
|
||||
- EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign);
|
||||
-#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
|
||||
-
|
||||
- if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
|
||||
+ RSA_METHOD *rsa_meth;
|
||||
+ EC_KEY_METHOD *ec_meth;
|
||||
+
|
||||
+ if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL)
|
||||
+ return -1;
|
||||
+ EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL);
|
||||
+ EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign);
|
||||
+ EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish,
|
||||
+ &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public);
|
||||
+ EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish,
|
||||
+ ec_copy, ec_set_group, ec_set_private, ec_set_public);
|
||||
+
|
||||
+ if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL)
|
||||
fatal("%s: RSA_meth_dup failed", __func__);
|
||||
- if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
|
||||
- !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
|
||||
+ helper->rsa_finish = RSA_meth_get_finish(rsa_meth);
|
||||
+ if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") ||
|
||||
+ !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) ||
|
||||
+ !RSA_meth_set_finish(rsa_meth, rsa_finish))
|
||||
fatal("%s: failed to prepare method", __func__);
|
||||
|
||||
- return (0);
|
||||
+ helper->ec_meth = ec_meth;
|
||||
+ helper->rsa_meth = rsa_meth;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static int
|
||||
-pkcs11_start_helper(void)
|
||||
+static struct helper *
|
||||
+pkcs11_start_helper(const char *path)
|
||||
{
|
||||
int pair[2];
|
||||
- char *helper, *verbosity = NULL;
|
||||
-
|
||||
- if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
|
||||
- verbosity = "-vvv";
|
||||
-
|
||||
- if (pkcs11_start_helper_methods() == -1) {
|
||||
- error("pkcs11_start_helper_methods failed");
|
||||
- return (-1);
|
||||
- }
|
||||
+ char *prog, *verbosity = NULL;
|
||||
+ struct helper *helper;
|
||||
+ pid_t pid;
|
||||
|
||||
+ if (nhelpers >= INT_MAX)
|
||||
+ fatal("%s: too many helpers", __func__);
|
||||
+ debug3("%s: start helper for %s", __func__, path);
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||
error("socketpair: %s", strerror(errno));
|
||||
- return (-1);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ helper = xcalloc(1, sizeof(*helper));
|
||||
+ if (pkcs11_start_helper_methods(helper) == -1) {
|
||||
+ error("pkcs11_start_helper_methods failed");
|
||||
+ goto fail;
|
||||
}
|
||||
if ((pid = fork()) == -1) {
|
||||
error("fork: %s", strerror(errno));
|
||||
- return (-1);
|
||||
+ fail:
|
||||
+ close(pair[0]);
|
||||
+ close(pair[1]);
|
||||
+ RSA_meth_free(helper->rsa_meth);
|
||||
+ EC_KEY_METHOD_free(helper->ec_meth);
|
||||
+ free(helper);
|
||||
+ return NULL;
|
||||
} else if (pid == 0) {
|
||||
if ((dup2(pair[1], STDIN_FILENO) == -1) ||
|
||||
(dup2(pair[1], STDOUT_FILENO) == -1)) {
|
||||
@@ -297,18 +485,27 @@ pkcs11_start_helper(void)
|
||||
}
|
||||
close(pair[0]);
|
||||
close(pair[1]);
|
||||
- helper = getenv("SSH_PKCS11_HELPER");
|
||||
- if (helper == NULL || strlen(helper) == 0)
|
||||
- helper = _PATH_SSH_PKCS11_HELPER;
|
||||
+ prog = getenv("SSH_PKCS11_HELPER");
|
||||
+ if (prog == NULL || strlen(prog) == 0)
|
||||
+ prog = _PATH_SSH_PKCS11_HELPER;
|
||||
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
|
||||
+ verbosity = "-vvv";
|
||||
debug("%s: starting %s %s", __func__, helper,
|
||||
verbosity == NULL ? "" : verbosity);
|
||||
- execlp(helper, helper, verbosity, (char *)NULL);
|
||||
- fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
|
||||
+ execlp(prog, prog, verbosity, (char *)NULL);
|
||||
+ fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno));
|
||||
_exit(1);
|
||||
}
|
||||
close(pair[1]);
|
||||
- fd = pair[0];
|
||||
- return (0);
|
||||
+ helper->fd = pair[0];
|
||||
+ helper->path = xstrdup(path);
|
||||
+ helper->pid = pid;
|
||||
+ debug3("%s: helper %zu for \"%s\" on fd %d pid %ld", __func__, nhelpers,
|
||||
+ helper->path, helper->fd, (long)helper->pid);
|
||||
+ helpers = xrecallocarray(helpers, nhelpers,
|
||||
+ nhelpers + 1, sizeof(*helpers));
|
||||
+ helpers[nhelpers++] = helper;
|
||||
+ return helper;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -322,9 +519,11 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
||||
size_t blen;
|
||||
u_int nkeys, i;
|
||||
struct sshbuf *msg;
|
||||
+ struct helper *helper;
|
||||
|
||||
- if (fd < 0 && pkcs11_start_helper() < 0)
|
||||
- return (-1);
|
||||
+ if ((helper = helper_by_provider(name)) == NULL &&
|
||||
+ (helper = pkcs11_start_helper(name)) == NULL)
|
||||
+ return -1;
|
||||
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
@@ -332,10 +531,10 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
||||
(r = sshbuf_put_cstring(msg, name)) != 0 ||
|
||||
(r = sshbuf_put_cstring(msg, pin)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
- send_msg(msg);
|
||||
+ send_msg(helper->fd, msg);
|
||||
sshbuf_reset(msg);
|
||||
|
||||
- type = recv_msg(msg);
|
||||
+ type = recv_msg(helper->fd, msg);
|
||||
if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
@@ -350,7 +549,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
||||
__func__, ssh_err(r));
|
||||
if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
|
||||
fatal("%s: bad key: %s", __func__, ssh_err(r));
|
||||
- wrap_key(k);
|
||||
+ wrap_key(helper, k);
|
||||
(*keysp)[i] = k;
|
||||
if (labelsp)
|
||||
(*labelsp)[i] = label;
|
||||
@@ -371,22 +570,15 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
|
||||
int
|
||||
pkcs11_del_provider(char *name)
|
||||
{
|
||||
- int r, ret = -1;
|
||||
- struct sshbuf *msg;
|
||||
-
|
||||
- if ((msg = sshbuf_new()) == NULL)
|
||||
- fatal("%s: sshbuf_new failed", __func__);
|
||||
- if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
|
||||
- (r = sshbuf_put_cstring(msg, name)) != 0 ||
|
||||
- (r = sshbuf_put_cstring(msg, "")) != 0)
|
||||
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
- send_msg(msg);
|
||||
- sshbuf_reset(msg);
|
||||
-
|
||||
- if (recv_msg(msg) == SSH_AGENT_SUCCESS)
|
||||
- ret = 0;
|
||||
- sshbuf_free(msg);
|
||||
- return (ret);
|
||||
+ struct helper *helper;
|
||||
+
|
||||
+ /*
|
||||
+ * ssh-agent deletes keys before calling this, so the helper entry
|
||||
+ * should be gone before we get here.
|
||||
+ */
|
||||
+ debug3("%s: delete %s", __func__, name);
|
||||
+ if ((helper = helper_by_provider(name)) != NULL)
|
||||
+ helper_terminate(helper);
|
||||
+ return 0;
|
||||
}
|
||||
-
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,171 @@
|
||||
From 2f1be98e83feb90665b9292eff8bb734537fd491 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Wed, 19 Jul 2023 14:02:27 +0000
|
||||
Subject: [PATCH 03/12] upstream: Ensure FIDO/PKCS11 libraries contain expected
|
||||
symbols
|
||||
|
||||
This checks via nlist(3) that candidate provider libraries contain one
|
||||
of the symbols that we will require prior to dlopen(), which can cause
|
||||
a number of side effects, including execution of constructors.
|
||||
|
||||
Feedback deraadt; ok markus
|
||||
|
||||
OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/29ef8a04866ca14688d5b7fed7b8b9deab851f77]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
misc.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
misc.h | 1 +
|
||||
ssh-pkcs11.c | 4 +++
|
||||
ssh-sk.c | 6 ++--
|
||||
4 files changed, 86 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/misc.c b/misc.c
|
||||
index 3a31d5c..8a107e4 100644
|
||||
--- a/misc.c
|
||||
+++ b/misc.c
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
+#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
@@ -41,6 +42,9 @@
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
+#ifdef HAVE_NLIST_H
|
||||
+#include <nlist.h>
|
||||
+#endif
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
@@ -2266,3 +2270,76 @@ ssh_signal(int signum, sshsig_t handler)
|
||||
}
|
||||
return osa.sa_handler;
|
||||
}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Returns zero if the library at 'path' contains symbol 's', nonzero
|
||||
+ * otherwise.
|
||||
+ */
|
||||
+int
|
||||
+lib_contains_symbol(const char *path, const char *s)
|
||||
+{
|
||||
+#ifdef HAVE_NLIST_H
|
||||
+ struct nlist nl[2];
|
||||
+ int ret = -1, r;
|
||||
+
|
||||
+ memset(nl, 0, sizeof(nl));
|
||||
+ nl[0].n_name = xstrdup(s);
|
||||
+ nl[1].n_name = NULL;
|
||||
+ if ((r = nlist(path, nl)) == -1) {
|
||||
+ error("%s: nlist failed for %s", __func__, path);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) {
|
||||
+ error("%s: library %s does not contain symbol %s", __func__, path, s);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* success */
|
||||
+ ret = 0;
|
||||
+ out:
|
||||
+ free(nl[0].n_name);
|
||||
+ return ret;
|
||||
+#else /* HAVE_NLIST_H */
|
||||
+ int fd, ret = -1;
|
||||
+ struct stat st;
|
||||
+ void *m = NULL;
|
||||
+ size_t sz = 0;
|
||||
+
|
||||
+ memset(&st, 0, sizeof(st));
|
||||
+ if ((fd = open(path, O_RDONLY)) < 0) {
|
||||
+ error("%s: open %s: %s", __func__, path, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if (fstat(fd, &st) != 0) {
|
||||
+ error("%s: fstat %s: %s", __func__, path, strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (!S_ISREG(st.st_mode)) {
|
||||
+ error("%s: %s is not a regular file", __func__, path);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (st.st_size < 0 ||
|
||||
+ (size_t)st.st_size < strlen(s) ||
|
||||
+ st.st_size >= INT_MAX/2) {
|
||||
+ error("%s: %s bad size %lld", __func__, path, (long long)st.st_size);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ sz = (size_t)st.st_size;
|
||||
+ if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED ||
|
||||
+ m == NULL) {
|
||||
+ error("%s: mmap %s: %s", __func__, path, strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (memmem(m, sz, s, strlen(s)) == NULL) {
|
||||
+ error("%s: %s does not contain expected string %s", __func__, path, s);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* success */
|
||||
+ ret = 0;
|
||||
+ out:
|
||||
+ if (m != NULL && m != MAP_FAILED)
|
||||
+ munmap(m, sz);
|
||||
+ close(fd);
|
||||
+ return ret;
|
||||
+#endif /* HAVE_NLIST_H */
|
||||
+}
|
||||
diff --git a/misc.h b/misc.h
|
||||
index 4a05db2..3f9f4db 100644
|
||||
--- a/misc.h
|
||||
+++ b/misc.h
|
||||
@@ -86,6 +86,7 @@ const char *atoi_err(const char *, int *);
|
||||
int parse_absolute_time(const char *, uint64_t *);
|
||||
void format_absolute_time(uint64_t, char *, size_t);
|
||||
int path_absolute(const char *);
|
||||
+int lib_contains_symbol(const char *, const char *);
|
||||
|
||||
void sock_set_v6only(int);
|
||||
|
||||
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
|
||||
index b56a41b..639a6f7 100644
|
||||
--- a/ssh-pkcs11.c
|
||||
+++ b/ssh-pkcs11.c
|
||||
@@ -1499,6 +1499,10 @@ pkcs11_register_provider(char *provider_id, char *pin,
|
||||
__func__, provider_id);
|
||||
goto fail;
|
||||
}
|
||||
+ if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
|
||||
+ error("provider %s is not a PKCS11 library", provider_id);
|
||||
+ goto fail;
|
||||
+ }
|
||||
/* open shared pkcs11-library */
|
||||
if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
|
||||
error("dlopen %s failed: %s", provider_id, dlerror());
|
||||
diff --git a/ssh-sk.c b/ssh-sk.c
|
||||
index 5ff9381..9df12cc 100644
|
||||
--- a/ssh-sk.c
|
||||
+++ b/ssh-sk.c
|
||||
@@ -119,10 +119,12 @@ sshsk_open(const char *path)
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
- if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
|
||||
- error("Provider \"%s\" dlopen failed: %s", path, dlerror());
|
||||
+ if (lib_contains_symbol(path, "sk_api_version") != 0) {
|
||||
+ error("provider %s is not an OpenSSH FIDO library", path);
|
||||
goto fail;
|
||||
}
|
||||
+ if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL)
|
||||
+ fatal("Provider \"%s\" dlopen failed: %s", path, dlerror());
|
||||
if ((ret->sk_api_version = dlsym(ret->dlhandle,
|
||||
"sk_api_version")) == NULL) {
|
||||
error("Provider \"%s\" dlsym(sk_api_version) failed: %s",
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0862f338941bfdfb2cadee87de6d5fdca1b8f457 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Wed, 19 Jul 2023 13:55:53 +0000
|
||||
Subject: [PATCH 04/12] upstream: terminate process if requested to load a
|
||||
PKCS#11 provider that isn't a PKCS#11 provider; from / ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/892506b13654301f69f9545f48213fc210e5c5cc]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-pkcs11.c | 6 ++----
|
||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
|
||||
index 639a6f7..7530acc 100644
|
||||
--- a/ssh-pkcs11.c
|
||||
+++ b/ssh-pkcs11.c
|
||||
@@ -1508,10 +1508,8 @@ pkcs11_register_provider(char *provider_id, char *pin,
|
||||
error("dlopen %s failed: %s", provider_id, dlerror());
|
||||
goto fail;
|
||||
}
|
||||
- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
|
||||
- error("dlsym(C_GetFunctionList) failed: %s", dlerror());
|
||||
- goto fail;
|
||||
- }
|
||||
+ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
|
||||
+ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
|
||||
p = xcalloc(1, sizeof(*p));
|
||||
p->name = xstrdup(provider_id);
|
||||
p->handle = handle;
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,194 @@
|
||||
From a6cee3905edf070c0de135d3f2ee5b74da1dbd28 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Tue, 26 May 2020 01:26:58 +0000
|
||||
Subject: [PATCH 05/12] upstream: Restrict ssh-agent from signing web
|
||||
challenges for FIDO
|
||||
|
||||
keys.
|
||||
|
||||
When signing messages in ssh-agent using a FIDO key that has an
|
||||
application string that does not start with "ssh:", ensure that the
|
||||
message being signed is one of the forms expected for the SSH protocol
|
||||
(currently pubkey authentication and sshsig signatures).
|
||||
|
||||
This prevents ssh-agent forwarding on a host that has FIDO keys
|
||||
attached granting the ability for the remote side to sign challenges
|
||||
for web authentication using those keys too.
|
||||
|
||||
Note that the converse case of web browsers signing SSH challenges is
|
||||
already precluded because no web RP can have the "ssh:" prefix in the
|
||||
application string that we require.
|
||||
|
||||
ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 9ab6012574ed0352d2f097d307f4a988222d1b19
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/0c111eb84efba7c2a38b2cc3278901a0123161b9]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 100 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index ceb348c..1794f35 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.255 2020/02/06 22:30:54 naddy Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -77,6 +77,7 @@
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
+#include "ssh2.h"
|
||||
#include "sshbuf.h"
|
||||
#include "sshkey.h"
|
||||
#include "authfd.h"
|
||||
@@ -167,6 +168,9 @@ static long lifetime = 0;
|
||||
|
||||
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
|
||||
|
||||
+/* Refuse signing of non-SSH messages for web-origin FIDO keys */
|
||||
+static int restrict_websafe = 1;
|
||||
+
|
||||
static void
|
||||
close_socket(SocketEntry *e)
|
||||
{
|
||||
@@ -282,6 +286,80 @@ agent_decode_alg(struct sshkey *key, u_int flags)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * This function inspects a message to be signed by a FIDO key that has a
|
||||
+ * web-like application string (i.e. one that does not begin with "ssh:".
|
||||
+ * It checks that the message is one of those expected for SSH operations
|
||||
+ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
|
||||
+ * for the web.
|
||||
+ */
|
||||
+static int
|
||||
+check_websafe_message_contents(struct sshkey *key,
|
||||
+ const u_char *msg, size_t len)
|
||||
+{
|
||||
+ int matched = 0;
|
||||
+ struct sshbuf *b;
|
||||
+ u_char m, n;
|
||||
+ char *cp1 = NULL, *cp2 = NULL;
|
||||
+ int r;
|
||||
+ struct sshkey *mkey = NULL;
|
||||
+
|
||||
+ if ((b = sshbuf_from(msg, len)) == NULL)
|
||||
+ fatal("%s: sshbuf_new", __func__);
|
||||
+
|
||||
+ /* SSH userauth request */
|
||||
+ if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */
|
||||
+ (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */
|
||||
+ (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */
|
||||
+ (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */
|
||||
+ (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */
|
||||
+ (r = sshkey_froms(b, &mkey)) == 0 && /* key */
|
||||
+ sshbuf_len(b) == 0) {
|
||||
+ debug("%s: parsed userauth", __func__);
|
||||
+ if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 &&
|
||||
+ strcmp(cp1, "ssh-connection") == 0 &&
|
||||
+ strcmp(cp2, "publickey") == 0 &&
|
||||
+ sshkey_equal(key, mkey)) {
|
||||
+ debug("%s: well formed userauth", __func__);
|
||||
+ matched = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ free(cp1);
|
||||
+ free(cp2);
|
||||
+ sshkey_free(mkey);
|
||||
+ sshbuf_free(b);
|
||||
+ if (matched)
|
||||
+ return 1;
|
||||
+
|
||||
+ if ((b = sshbuf_from(msg, len)) == NULL)
|
||||
+ fatal("%s: sshbuf_new", __func__);
|
||||
+ cp1 = cp2 = NULL;
|
||||
+ mkey = NULL;
|
||||
+
|
||||
+ /* SSHSIG */
|
||||
+ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 &&
|
||||
+ (r = sshbuf_consume(b, 6)) == 0 &&
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */
|
||||
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */
|
||||
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */
|
||||
+ sshbuf_len(b) == 0) {
|
||||
+ debug("%s: parsed sshsig", __func__);
|
||||
+ matched = 1;
|
||||
+ }
|
||||
+
|
||||
+ sshbuf_free(b);
|
||||
+ if (matched)
|
||||
+ return 1;
|
||||
+
|
||||
+ /* XXX CA signature operation */
|
||||
+
|
||||
+ error("web-origin key attempting to sign non-SSH message");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* ssh2 only */
|
||||
static void
|
||||
process_sign_request2(SocketEntry *e)
|
||||
@@ -314,14 +392,20 @@ process_sign_request2(SocketEntry *e)
|
||||
verbose("%s: user refused key", __func__);
|
||||
goto send;
|
||||
}
|
||||
- if (sshkey_is_sk(id->key) &&
|
||||
- (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
|
||||
- if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
|
||||
- SSH_FP_DEFAULT)) == NULL)
|
||||
- fatal("%s: fingerprint failed", __func__);
|
||||
- notifier = notify_start(0,
|
||||
- "Confirm user presence for key %s %s",
|
||||
- sshkey_type(id->key), fp);
|
||||
+ if (sshkey_is_sk(id->key)) {
|
||||
+ if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
|
||||
+ !check_websafe_message_contents(key, data, dlen)) {
|
||||
+ /* error already logged */
|
||||
+ goto send;
|
||||
+ }
|
||||
+ if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
|
||||
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
|
||||
+ SSH_FP_DEFAULT)) == NULL)
|
||||
+ fatal("%s: fingerprint failed", __func__);
|
||||
+ notifier = notify_start(0,
|
||||
+ "Confirm user presence for key %s %s",
|
||||
+ sshkey_type(id->key), fp);
|
||||
+ }
|
||||
}
|
||||
if ((r = sshkey_sign(id->key, &signature, &slen,
|
||||
data, dlen, agent_decode_alg(key, flags),
|
||||
@@ -1214,7 +1298,7 @@ main(int ac, char **av)
|
||||
__progname = ssh_get_progname(av[0]);
|
||||
seed_rng();
|
||||
|
||||
- while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
|
||||
+ while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'E':
|
||||
fingerprint_hash = ssh_digest_alg_by_name(optarg);
|
||||
@@ -1229,6 +1313,12 @@ main(int ac, char **av)
|
||||
case 'k':
|
||||
k_flag++;
|
||||
break;
|
||||
+ case 'O':
|
||||
+ if (strcmp(optarg, "no-restrict-websafe") == 0)
|
||||
+ restrict_websafe = 0;
|
||||
+ else
|
||||
+ fatal("Unknown -O option");
|
||||
+ break;
|
||||
case 'P':
|
||||
if (provider_whitelist != NULL)
|
||||
fatal("-P option already specified");
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,73 @@
|
||||
From a5d845b7b42861d18f43e83de9f24c7374d1b458 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Fri, 18 Sep 2020 08:16:38 +0000
|
||||
Subject: [PATCH 06/12] upstream: handle multiple messages in a single read()
|
||||
|
||||
PR#183 by Dennis Kaarsemaker; feedback and ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 8570bb4d02d00cf70b98590716ea6a7d1cce68d1
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/52a03e9fca2d74eef953ddd4709250f365ca3975]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 19 +++++++++++++------
|
||||
1 file changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 1794f35..78f7268 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.258 2020/05/26 01:26:58 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.264 2020/09/18 08:16:38 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -853,8 +853,10 @@ send:
|
||||
}
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
|
||||
-/* dispatch incoming messages */
|
||||
-
|
||||
+/*
|
||||
+ * dispatch incoming message.
|
||||
+ * returns 1 on success, 0 for incomplete messages or -1 on error.
|
||||
+ */
|
||||
static int
|
||||
process_message(u_int socknum)
|
||||
{
|
||||
@@ -908,7 +910,7 @@ process_message(u_int socknum)
|
||||
/* send a fail message for all other request types */
|
||||
send_status(e, 0);
|
||||
}
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
@@ -952,7 +954,7 @@ process_message(u_int socknum)
|
||||
send_status(e, 0);
|
||||
break;
|
||||
}
|
||||
- return 0;
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1043,7 +1045,12 @@ handle_conn_read(u_int socknum)
|
||||
if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
explicit_bzero(buf, sizeof(buf));
|
||||
- process_message(socknum);
|
||||
+ for (;;) {
|
||||
+ if ((r = process_message(socknum)) == -1)
|
||||
+ return -1;
|
||||
+ else if (r == 0)
|
||||
+ break;
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,125 @@
|
||||
From 653cc18c922fc387b3d3aa1b081c5e5283cce28a Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Tue, 26 Jan 2021 00:47:47 +0000
|
||||
Subject: [PATCH 07/12] upstream: use recallocarray to allocate the agent
|
||||
sockets table;
|
||||
|
||||
also clear socket entries that are being marked as unused.
|
||||
|
||||
spinkle in some debug2() spam to make it easier to watch an agent
|
||||
do its thing.
|
||||
|
||||
ok markus
|
||||
|
||||
OpenBSD-Commit-ID: 74582c8e82e96afea46f6c7b6813a429cbc75922
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1fe16fd61bb53944ec510882acc0491abd66ff76]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 20 ++++++++++++++++----
|
||||
1 file changed, 16 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 78f7268..2635bc5 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.264 2020/09/18 08:16:38 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.269 2021/01/26 00:47:47 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -175,11 +175,12 @@ static void
|
||||
close_socket(SocketEntry *e)
|
||||
{
|
||||
close(e->fd);
|
||||
- e->fd = -1;
|
||||
- e->type = AUTH_UNUSED;
|
||||
sshbuf_free(e->input);
|
||||
sshbuf_free(e->output);
|
||||
sshbuf_free(e->request);
|
||||
+ memset(e, '\0', sizeof(*e));
|
||||
+ e->fd = -1;
|
||||
+ e->type = AUTH_UNUSED;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -249,6 +250,8 @@ process_request_identities(SocketEntry *e)
|
||||
struct sshbuf *msg;
|
||||
int r;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
+
|
||||
if ((msg = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
|
||||
@@ -441,6 +444,7 @@ process_remove_identity(SocketEntry *e)
|
||||
struct sshkey *key = NULL;
|
||||
Identity *id;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
if ((r = sshkey_froms(e->request, &key)) != 0) {
|
||||
error("%s: get key: %s", __func__, ssh_err(r));
|
||||
goto done;
|
||||
@@ -467,6 +471,7 @@ process_remove_all_identities(SocketEntry *e)
|
||||
{
|
||||
Identity *id;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
/* Loop over all identities and clear the keys. */
|
||||
for (id = TAILQ_FIRST(&idtab->idlist); id;
|
||||
id = TAILQ_FIRST(&idtab->idlist)) {
|
||||
@@ -520,6 +525,7 @@ process_add_identity(SocketEntry *e)
|
||||
u_char ctype;
|
||||
int r = SSH_ERR_INTERNAL_ERROR;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
|
||||
k == NULL ||
|
||||
(r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
|
||||
@@ -667,6 +673,7 @@ process_lock_agent(SocketEntry *e, int lock)
|
||||
static u_int fail_count = 0;
|
||||
size_t pwlen;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
/*
|
||||
* This is deliberately fatal: the user has requested that we lock,
|
||||
* but we can't parse their request properly. The only safe thing to
|
||||
@@ -738,6 +745,7 @@ process_add_smartcard_key(SocketEntry *e)
|
||||
struct sshkey **keys = NULL, *k;
|
||||
Identity *id;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
|
||||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
|
||||
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
@@ -818,6 +826,7 @@ process_remove_smartcard_key(SocketEntry *e)
|
||||
int r, success = 0;
|
||||
Identity *id, *nxt;
|
||||
|
||||
+ debug2("%s: entering", __func__);
|
||||
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
|
||||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
|
||||
error("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
@@ -962,6 +971,8 @@ new_socket(sock_type type, int fd)
|
||||
{
|
||||
u_int i, old_alloc, new_alloc;
|
||||
|
||||
+ debug("%s: type = %s", __func__, type == AUTH_CONNECTION ? "CONNECTION" :
|
||||
+ (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
|
||||
set_nonblock(fd);
|
||||
|
||||
if (fd > max_fd)
|
||||
@@ -981,7 +992,8 @@ new_socket(sock_type type, int fd)
|
||||
}
|
||||
old_alloc = sockets_alloc;
|
||||
new_alloc = sockets_alloc + 10;
|
||||
- sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
|
||||
+ sockets = xrecallocarray(sockets, old_alloc, new_alloc,
|
||||
+ sizeof(sockets[0]));
|
||||
for (i = old_alloc; i < new_alloc; i++)
|
||||
sockets[i].type = AUTH_UNUSED;
|
||||
sockets_alloc = new_alloc;
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,315 @@
|
||||
From c30158ea225cf8ad67c3dcc88fa9e4afbf8959a7 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Tue, 26 Jan 2021 00:53:31 +0000
|
||||
Subject: [PATCH 08/12] upstream: more ssh-agent refactoring
|
||||
|
||||
Allow confirm_key() to accept an additional reason suffix
|
||||
|
||||
Factor publickey userauth parsing out into its own function and allow
|
||||
it to optionally return things it parsed out of the message to its
|
||||
caller.
|
||||
|
||||
feedback/ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 29006515617d1aa2d8b85cd2bf667e849146477e
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/e0e8bee8024fa9e31974244d14f03d799e5c0775]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 197 ++++++++++++++++++++++++++++++++++------------------
|
||||
1 file changed, 130 insertions(+), 67 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 2635bc5..7ad323c 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.269 2021/01/26 00:47:47 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.270 2021/01/26 00:53:31 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -216,15 +216,16 @@ lookup_identity(struct sshkey *key)
|
||||
|
||||
/* Check confirmation of keysign request */
|
||||
static int
|
||||
-confirm_key(Identity *id)
|
||||
+confirm_key(Identity *id, const char *extra)
|
||||
{
|
||||
char *p;
|
||||
int ret = -1;
|
||||
|
||||
p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
|
||||
if (p != NULL &&
|
||||
- ask_permission("Allow use of key %s?\nKey fingerprint %s.",
|
||||
- id->comment, p))
|
||||
+ ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
|
||||
+ id->comment, p,
|
||||
+ extra == NULL ? "" : "\n", extra == NULL ? "" : extra))
|
||||
ret = 0;
|
||||
free(p);
|
||||
|
||||
@@ -290,74 +291,133 @@ agent_decode_alg(struct sshkey *key, u_int flags)
|
||||
}
|
||||
|
||||
/*
|
||||
- * This function inspects a message to be signed by a FIDO key that has a
|
||||
- * web-like application string (i.e. one that does not begin with "ssh:".
|
||||
- * It checks that the message is one of those expected for SSH operations
|
||||
- * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
|
||||
- * for the web.
|
||||
+ * Attempt to parse the contents of a buffer as a SSH publickey userauth
|
||||
+ * request, checking its contents for consistency and matching the embedded
|
||||
+ * key against the one that is being used for signing.
|
||||
+ * Note: does not modify msg buffer.
|
||||
+ * Optionally extract the username and session ID from the request.
|
||||
*/
|
||||
static int
|
||||
-check_websafe_message_contents(struct sshkey *key,
|
||||
- const u_char *msg, size_t len)
|
||||
+parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
|
||||
+ char **userp, struct sshbuf **sess_idp)
|
||||
{
|
||||
- int matched = 0;
|
||||
- struct sshbuf *b;
|
||||
- u_char m, n;
|
||||
- char *cp1 = NULL, *cp2 = NULL;
|
||||
+ struct sshbuf *b = NULL, *sess_id = NULL;
|
||||
+ char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
|
||||
int r;
|
||||
+ u_char t, sig_follows;
|
||||
struct sshkey *mkey = NULL;
|
||||
|
||||
- if ((b = sshbuf_from(msg, len)) == NULL)
|
||||
- fatal("%s: sshbuf_new", __func__);
|
||||
+ if (userp != NULL)
|
||||
+ *userp = NULL;
|
||||
+ if (sess_idp != NULL)
|
||||
+ *sess_idp = NULL;
|
||||
+ if ((b = sshbuf_fromb(msg)) == NULL)
|
||||
+ fatal("%s: sshbuf_fromb", __func__);
|
||||
|
||||
/* SSH userauth request */
|
||||
- if ((r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* sess_id */
|
||||
- (r = sshbuf_get_u8(b, &m)) == 0 && /* SSH2_MSG_USERAUTH_REQUEST */
|
||||
- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* server user */
|
||||
- (r = sshbuf_get_cstring(b, &cp1, NULL)) == 0 && /* service */
|
||||
- (r = sshbuf_get_cstring(b, &cp2, NULL)) == 0 && /* method */
|
||||
- (r = sshbuf_get_u8(b, &n)) == 0 && /* sig-follows */
|
||||
- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* alg */
|
||||
- (r = sshkey_froms(b, &mkey)) == 0 && /* key */
|
||||
- sshbuf_len(b) == 0) {
|
||||
- debug("%s: parsed userauth", __func__);
|
||||
- if (m == SSH2_MSG_USERAUTH_REQUEST && n == 1 &&
|
||||
- strcmp(cp1, "ssh-connection") == 0 &&
|
||||
- strcmp(cp2, "publickey") == 0 &&
|
||||
- sshkey_equal(key, mkey)) {
|
||||
- debug("%s: well formed userauth", __func__);
|
||||
- matched = 1;
|
||||
- }
|
||||
+ if ((r = sshbuf_froms(b, &sess_id)) != 0)
|
||||
+ goto out;
|
||||
+ if (sshbuf_len(sess_id) == 0) {
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
+ goto out;
|
||||
}
|
||||
- free(cp1);
|
||||
- free(cp2);
|
||||
- sshkey_free(mkey);
|
||||
+ if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
|
||||
+ (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */
|
||||
+ (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */
|
||||
+ (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */
|
||||
+ (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */
|
||||
+ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */
|
||||
+ (r = sshkey_froms(b, &mkey)) != 0) /* key */
|
||||
+ goto out;
|
||||
+ if (t != SSH2_MSG_USERAUTH_REQUEST ||
|
||||
+ sig_follows != 1 ||
|
||||
+ strcmp(service, "ssh-connection") != 0 ||
|
||||
+ !sshkey_equal(expected_key, mkey) ||
|
||||
+ sshkey_type_from_name(pkalg) != expected_key->type) {
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (strcmp(method, "publickey") != 0) {
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (sshbuf_len(b) != 0) {
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ debug("%s: well formed userauth", __func__);
|
||||
+ if (userp != NULL) {
|
||||
+ *userp = user;
|
||||
+ user = NULL;
|
||||
+ }
|
||||
+ if (sess_idp != NULL) {
|
||||
+ *sess_idp = sess_id;
|
||||
+ sess_id = NULL;
|
||||
+ }
|
||||
+ out:
|
||||
sshbuf_free(b);
|
||||
- if (matched)
|
||||
- return 1;
|
||||
+ sshbuf_free(sess_id);
|
||||
+ free(user);
|
||||
+ free(service);
|
||||
+ free(method);
|
||||
+ free(pkalg);
|
||||
+ sshkey_free(mkey);
|
||||
+ return r;
|
||||
+}
|
||||
|
||||
- if ((b = sshbuf_from(msg, len)) == NULL)
|
||||
- fatal("%s: sshbuf_new", __func__);
|
||||
- cp1 = cp2 = NULL;
|
||||
- mkey = NULL;
|
||||
-
|
||||
- /* SSHSIG */
|
||||
- if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) == 0 &&
|
||||
- (r = sshbuf_consume(b, 6)) == 0 &&
|
||||
- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* namespace */
|
||||
- (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* reserved */
|
||||
- (r = sshbuf_get_cstring(b, NULL, NULL)) == 0 && /* hashalg */
|
||||
- (r = sshbuf_get_string_direct(b, NULL, NULL)) == 0 && /* H(msg) */
|
||||
- sshbuf_len(b) == 0) {
|
||||
- debug("%s: parsed sshsig", __func__);
|
||||
- matched = 1;
|
||||
- }
|
||||
+/*
|
||||
+ * Attempt to parse the contents of a buffer as a SSHSIG signature request.
|
||||
+ * Note: does not modify buffer.
|
||||
+ */
|
||||
+static int
|
||||
+parse_sshsig_request(struct sshbuf *msg)
|
||||
+{
|
||||
+ int r;
|
||||
+ struct sshbuf *b;
|
||||
|
||||
+ if ((b = sshbuf_fromb(msg)) == NULL)
|
||||
+ fatal("%s: sshbuf_fromb", __func__);
|
||||
+
|
||||
+ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 ||
|
||||
+ (r = sshbuf_consume(b, 6)) != 0 ||
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */
|
||||
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */
|
||||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */
|
||||
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */
|
||||
+ goto out;
|
||||
+ if (sshbuf_len(b) != 0) {
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ out:
|
||||
sshbuf_free(b);
|
||||
- if (matched)
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * This function inspects a message to be signed by a FIDO key that has a
|
||||
+ * web-like application string (i.e. one that does not begin with "ssh:".
|
||||
+ * It checks that the message is one of those expected for SSH operations
|
||||
+ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
|
||||
+ * for the web.
|
||||
+ */
|
||||
+static int
|
||||
+check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
|
||||
+{
|
||||
+ if (parse_userauth_request(data, key, NULL, NULL) == 0) {
|
||||
+ debug("%s: signed data matches public key userauth request", __func__);
|
||||
return 1;
|
||||
+ }
|
||||
+ if (parse_sshsig_request(data) == 0) {
|
||||
+ debug("%s: signed data matches SSHSIG signature request", __func__);
|
||||
+ return 1;
|
||||
+ }
|
||||
|
||||
- /* XXX CA signature operation */
|
||||
+ /* XXX check CA signature operation */
|
||||
|
||||
error("web-origin key attempting to sign non-SSH message");
|
||||
return 0;
|
||||
@@ -367,21 +427,22 @@ check_websafe_message_contents(struct sshkey *key,
|
||||
static void
|
||||
process_sign_request2(SocketEntry *e)
|
||||
{
|
||||
- const u_char *data;
|
||||
u_char *signature = NULL;
|
||||
- size_t dlen, slen = 0;
|
||||
+ size_t i, slen = 0;
|
||||
u_int compat = 0, flags;
|
||||
int r, ok = -1;
|
||||
char *fp = NULL;
|
||||
- struct sshbuf *msg;
|
||||
+ struct sshbuf *msg = NULL, *data = NULL;
|
||||
struct sshkey *key = NULL;
|
||||
struct identity *id;
|
||||
struct notifier_ctx *notifier = NULL;
|
||||
|
||||
- if ((msg = sshbuf_new()) == NULL)
|
||||
+ debug("%s: entering", __func__);
|
||||
+
|
||||
+ if ((msg = sshbuf_new()) == NULL | (data = sshbuf_new()) == NULL)
|
||||
fatal("%s: sshbuf_new failed", __func__);
|
||||
if ((r = sshkey_froms(e->request, &key)) != 0 ||
|
||||
- (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
|
||||
+ (r = sshbuf_get_stringb(e->request, data)) != 0 ||
|
||||
(r = sshbuf_get_u32(e->request, &flags)) != 0) {
|
||||
error("%s: couldn't parse request: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
@@ -391,13 +452,13 @@ process_sign_request2(SocketEntry *e)
|
||||
verbose("%s: %s key not found", __func__, sshkey_type(key));
|
||||
goto send;
|
||||
}
|
||||
- if (id->confirm && confirm_key(id) != 0) {
|
||||
+ if (id->confirm && confirm_key(id, NULL) != 0) {
|
||||
verbose("%s: user refused key", __func__);
|
||||
goto send;
|
||||
}
|
||||
if (sshkey_is_sk(id->key)) {
|
||||
if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
|
||||
- !check_websafe_message_contents(key, data, dlen)) {
|
||||
+ !check_websafe_message_contents(key, data)) {
|
||||
/* error already logged */
|
||||
goto send;
|
||||
}
|
||||
@@ -411,7 +472,7 @@ process_sign_request2(SocketEntry *e)
|
||||
}
|
||||
}
|
||||
if ((r = sshkey_sign(id->key, &signature, &slen,
|
||||
- data, dlen, agent_decode_alg(key, flags),
|
||||
+ sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags),
|
||||
id->sk_provider, compat)) != 0) {
|
||||
error("%s: sshkey_sign: %s", __func__, ssh_err(r));
|
||||
goto send;
|
||||
@@ -420,8 +481,7 @@ process_sign_request2(SocketEntry *e)
|
||||
ok = 0;
|
||||
send:
|
||||
notify_complete(notifier);
|
||||
- sshkey_free(key);
|
||||
- free(fp);
|
||||
+
|
||||
if (ok == 0) {
|
||||
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
|
||||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
|
||||
@@ -432,7 +492,10 @@ process_sign_request2(SocketEntry *e)
|
||||
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
||||
+ sshbuf_free(data);
|
||||
sshbuf_free(msg);
|
||||
+ sshkey_free(key);
|
||||
+ free(fp);
|
||||
free(signature);
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,38 @@
|
||||
From 7adba46611e5d076d7d12d9f4162dd4cabd5ff50 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Fri, 29 Jan 2021 06:28:10 +0000
|
||||
Subject: [PATCH 09/12] upstream: give typedef'd struct a struct name; makes
|
||||
the fuzzer I'm
|
||||
|
||||
writing a bit easier
|
||||
|
||||
OpenBSD-Commit-ID: 1052ab521505a4d8384d67acb3974ef81b8896cb
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/8afaa7d7918419d3da6c0477b83db2159879cb33]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 7ad323c..c99927c 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.270 2021/01/26 00:53:31 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.274 2021/01/29 06:28:10 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -108,7 +108,7 @@ typedef enum {
|
||||
AUTH_CONNECTION
|
||||
} sock_type;
|
||||
|
||||
-typedef struct {
|
||||
+typedef struct socket_entry {
|
||||
int fd;
|
||||
sock_type type;
|
||||
struct sshbuf *input;
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,39 @@
|
||||
From 343e2a2c0ef754a7a86118016b248f7a73f8d510 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Fri, 29 Jan 2021 06:29:46 +0000
|
||||
Subject: [PATCH 10/12] upstream: fix the values of enum sock_type
|
||||
|
||||
OpenBSD-Commit-ID: 18d048f4dbfbb159ff500cfc2700b8fb1407facd
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1a4b92758690faa12f49079dd3b72567f909466d]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index c99927c..7f1e14b 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.274 2021/01/29 06:28:10 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.275 2021/01/29 06:29:46 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -103,9 +103,9 @@
|
||||
#define AGENT_RBUF_LEN (4096)
|
||||
|
||||
typedef enum {
|
||||
- AUTH_UNUSED,
|
||||
- AUTH_SOCKET,
|
||||
- AUTH_CONNECTION
|
||||
+ AUTH_UNUSED = 0,
|
||||
+ AUTH_SOCKET = 1,
|
||||
+ AUTH_CONNECTION = 2,
|
||||
} sock_type;
|
||||
|
||||
typedef struct socket_entry {
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,307 @@
|
||||
From 2b3b369c8cf71f9ef5942a5e074e6f86e7ca1e0c Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Sun, 19 Dec 2021 22:09:23 +0000
|
||||
Subject: [PATCH 11/12] upstream: ssh-agent side of binding
|
||||
|
||||
record session ID/hostkey/forwarding status for each active socket.
|
||||
|
||||
Attempt to parse data-to-be-signed at signature request time and extract
|
||||
session ID from the blob if it is a pubkey userauth request.
|
||||
|
||||
ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: a80fd41e292b18b67508362129e9fed549abd318
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/4c1e3ce85e183a9d0c955c88589fed18e4d6a058]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
authfd.h | 3 +
|
||||
ssh-agent.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
2 files changed, 170 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/authfd.h b/authfd.h
|
||||
index c3bf625..9cc9807 100644
|
||||
--- a/authfd.h
|
||||
+++ b/authfd.h
|
||||
@@ -76,6 +76,9 @@ int ssh_agent_sign(int sock, const struct sshkey *key,
|
||||
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
|
||||
#define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
|
||||
|
||||
+/* generic extension mechanism */
|
||||
+#define SSH_AGENTC_EXTENSION 27
|
||||
+
|
||||
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||
#define SSH_AGENT_CONSTRAIN_MAXSIGN 3
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 7f1e14b..01c7f2b 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.275 2021/01/29 06:29:46 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.280 2021/12/19 22:09:23 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -98,9 +98,15 @@
|
||||
#endif
|
||||
|
||||
/* Maximum accepted message length */
|
||||
-#define AGENT_MAX_LEN (256*1024)
|
||||
+#define AGENT_MAX_LEN (256*1024)
|
||||
/* Maximum bytes to read from client socket */
|
||||
-#define AGENT_RBUF_LEN (4096)
|
||||
+#define AGENT_RBUF_LEN (4096)
|
||||
+/* Maximum number of recorded session IDs/hostkeys per connection */
|
||||
+#define AGENT_MAX_SESSION_IDS 16
|
||||
+/* Maximum size of session ID */
|
||||
+#define AGENT_MAX_SID_LEN 128
|
||||
+
|
||||
+/* XXX store hostkey_sid in a refcounted tree */
|
||||
|
||||
typedef enum {
|
||||
AUTH_UNUSED = 0,
|
||||
@@ -108,12 +114,20 @@ typedef enum {
|
||||
AUTH_CONNECTION = 2,
|
||||
} sock_type;
|
||||
|
||||
+struct hostkey_sid {
|
||||
+ struct sshkey *key;
|
||||
+ struct sshbuf *sid;
|
||||
+ int forwarded;
|
||||
+};
|
||||
+
|
||||
typedef struct socket_entry {
|
||||
int fd;
|
||||
sock_type type;
|
||||
struct sshbuf *input;
|
||||
struct sshbuf *output;
|
||||
struct sshbuf *request;
|
||||
+ size_t nsession_ids;
|
||||
+ struct hostkey_sid *session_ids;
|
||||
} SocketEntry;
|
||||
|
||||
u_int sockets_alloc = 0;
|
||||
@@ -174,10 +188,17 @@ static int restrict_websafe = 1;
|
||||
static void
|
||||
close_socket(SocketEntry *e)
|
||||
{
|
||||
+ size_t i;
|
||||
+
|
||||
close(e->fd);
|
||||
sshbuf_free(e->input);
|
||||
sshbuf_free(e->output);
|
||||
sshbuf_free(e->request);
|
||||
+ for (i = 0; i < e->nsession_ids; i++) {
|
||||
+ sshkey_free(e->session_ids[i].key);
|
||||
+ sshbuf_free(e->session_ids[i].sid);
|
||||
+ }
|
||||
+ free(e->session_ids);
|
||||
memset(e, '\0', sizeof(*e));
|
||||
e->fd = -1;
|
||||
e->type = AUTH_UNUSED;
|
||||
@@ -423,6 +444,18 @@ check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int
|
||||
+buf_equal(const struct sshbuf *a, const struct sshbuf *b)
|
||||
+{
|
||||
+ if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if (sshbuf_len(a) != sshbuf_len(b))
|
||||
+ return SSH_ERR_INVALID_FORMAT;
|
||||
+ if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0)
|
||||
+ return SSH_ERR_INVALID_FORMAT;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* ssh2 only */
|
||||
static void
|
||||
process_sign_request2(SocketEntry *e)
|
||||
@@ -431,8 +464,8 @@ process_sign_request2(SocketEntry *e)
|
||||
size_t i, slen = 0;
|
||||
u_int compat = 0, flags;
|
||||
int r, ok = -1;
|
||||
- char *fp = NULL;
|
||||
- struct sshbuf *msg = NULL, *data = NULL;
|
||||
+ char *fp = NULL, *user = NULL, *sig_dest = NULL;
|
||||
+ struct sshbuf *msg = NULL, *data = NULL, *sid = NULL;
|
||||
struct sshkey *key = NULL;
|
||||
struct identity *id;
|
||||
struct notifier_ctx *notifier = NULL;
|
||||
@@ -452,7 +485,33 @@ process_sign_request2(SocketEntry *e)
|
||||
verbose("%s: %s key not found", __func__, sshkey_type(key));
|
||||
goto send;
|
||||
}
|
||||
- if (id->confirm && confirm_key(id, NULL) != 0) {
|
||||
+ /*
|
||||
+ * If session IDs were recorded for this socket, then use them to
|
||||
+ * annotate the confirmation messages with the host keys.
|
||||
+ */
|
||||
+ if (e->nsession_ids > 0 &&
|
||||
+ parse_userauth_request(data, key, &user, &sid) == 0) {
|
||||
+ /*
|
||||
+ * session ID from userauth request should match the final
|
||||
+ * ID in the list recorded in the socket, unless the ssh
|
||||
+ * client at that point lacks the binding extension (or if
|
||||
+ * an attacker is trying to steal use of the agent).
|
||||
+ */
|
||||
+ i = e->nsession_ids - 1;
|
||||
+ if (buf_equal(sid, e->session_ids[i].sid) == 0) {
|
||||
+ if ((fp = sshkey_fingerprint(e->session_ids[i].key,
|
||||
+ SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL)
|
||||
+ fatal("%s: fingerprint failed", __func__);
|
||||
+ debug3("%s: destination %s %s (slot %zu)", __func__,
|
||||
+ sshkey_type(e->session_ids[i].key), fp, i);
|
||||
+ xasprintf(&sig_dest, "public key request for "
|
||||
+ "target user \"%s\" to %s %s", user,
|
||||
+ sshkey_type(e->session_ids[i].key), fp);
|
||||
+ free(fp);
|
||||
+ fp = NULL;
|
||||
+ }
|
||||
+ }//
|
||||
+ if (id->confirm && confirm_key(id, sig_dest) != 0) {
|
||||
verbose("%s: user refused key", __func__);
|
||||
goto send;
|
||||
}
|
||||
@@ -467,8 +526,10 @@ process_sign_request2(SocketEntry *e)
|
||||
SSH_FP_DEFAULT)) == NULL)
|
||||
fatal("%s: fingerprint failed", __func__);
|
||||
notifier = notify_start(0,
|
||||
- "Confirm user presence for key %s %s",
|
||||
- sshkey_type(id->key), fp);
|
||||
+ "Confirm user presence for key %s %s%s%s",
|
||||
+ sshkey_type(id->key), fp,
|
||||
+ sig_dest == NULL ? "" : "\n",
|
||||
+ sig_dest == NULL ? "" : sig_dest);
|
||||
}
|
||||
}
|
||||
if ((r = sshkey_sign(id->key, &signature, &slen,
|
||||
@@ -492,11 +553,14 @@ process_sign_request2(SocketEntry *e)
|
||||
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
|
||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
||||
|
||||
+ sshbuf_free(sid);
|
||||
sshbuf_free(data);
|
||||
sshbuf_free(msg);
|
||||
sshkey_free(key);
|
||||
free(fp);
|
||||
free(signature);
|
||||
+ free(sig_dest);
|
||||
+ free(user);
|
||||
}
|
||||
|
||||
/* shared */
|
||||
@@ -925,6 +989,98 @@ send:
|
||||
}
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
|
||||
+static int
|
||||
+process_ext_session_bind(SocketEntry *e)
|
||||
+{
|
||||
+ int r, sid_match, key_match;
|
||||
+ struct sshkey *key = NULL;
|
||||
+ struct sshbuf *sid = NULL, *sig = NULL;
|
||||
+ char *fp = NULL;
|
||||
+ u_char fwd;
|
||||
+ size_t i;
|
||||
+
|
||||
+ debug2("%s: entering", __func__);
|
||||
+ if ((r = sshkey_froms(e->request, &key)) != 0 ||
|
||||
+ (r = sshbuf_froms(e->request, &sid)) != 0 ||
|
||||
+ (r = sshbuf_froms(e->request, &sig)) != 0 ||
|
||||
+ (r = sshbuf_get_u8(e->request, &fwd)) != 0) {
|
||||
+ error("%s: parse: %s", __func__, ssh_err(r));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
|
||||
+ SSH_FP_DEFAULT)) == NULL)
|
||||
+ fatal("%s: fingerprint failed", __func__);
|
||||
+ /* check signature with hostkey on session ID */
|
||||
+ if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig),
|
||||
+ sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) {
|
||||
+ error("%s: sshkey_verify for %s %s: %s", __func__, sshkey_type(key), fp, ssh_err(r));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* check whether sid/key already recorded */
|
||||
+ for (i = 0; i < e->nsession_ids; i++) {
|
||||
+ sid_match = buf_equal(sid, e->session_ids[i].sid) == 0;
|
||||
+ key_match = sshkey_equal(key, e->session_ids[i].key);
|
||||
+ if (sid_match && key_match) {
|
||||
+ debug("%s: session ID already recorded for %s %s", __func__,
|
||||
+ sshkey_type(key), fp);
|
||||
+ r = 0;
|
||||
+ goto out;
|
||||
+ } else if (sid_match) {
|
||||
+ error("%s: session ID recorded against different key "
|
||||
+ "for %s %s", __func__, sshkey_type(key), fp);
|
||||
+ r = -1;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /*
|
||||
+ * new sid with previously-seen key can happen, e.g. multiple
|
||||
+ * connections to the same host.
|
||||
+ */
|
||||
+ }
|
||||
+ /* record new key/sid */
|
||||
+ if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) {
|
||||
+ error("%s: too many session IDs recorded", __func__);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids,
|
||||
+ e->nsession_ids + 1, sizeof(*e->session_ids));
|
||||
+ i = e->nsession_ids++;
|
||||
+ debug("%s: recorded %s %s (slot %zu of %d)", __func__, sshkey_type(key), fp, i,
|
||||
+ AGENT_MAX_SESSION_IDS);
|
||||
+ e->session_ids[i].key = key;
|
||||
+ e->session_ids[i].forwarded = fwd != 0;
|
||||
+ key = NULL; /* transferred */
|
||||
+ /* can't transfer sid; it's refcounted and scoped to request's life */
|
||||
+ if ((e->session_ids[i].sid = sshbuf_new()) == NULL)
|
||||
+ fatal("%s: sshbuf_new", __func__);
|
||||
+ if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0)
|
||||
+ fatal("%s: sshbuf_putb session ID: %s", __func__, ssh_err(r));
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ out:
|
||||
+ sshkey_free(key);
|
||||
+ sshbuf_free(sid);
|
||||
+ sshbuf_free(sig);
|
||||
+ return r == 0 ? 1 : 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+process_extension(SocketEntry *e)
|
||||
+{
|
||||
+ int r, success = 0;
|
||||
+ char *name;
|
||||
+
|
||||
+ debug2("%s: entering", __func__);
|
||||
+ if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) {
|
||||
+ error("%s: parse: %s", __func__, ssh_err(r));
|
||||
+ goto send;
|
||||
+ }
|
||||
+ if (strcmp(name, "session-bind@openssh.com") == 0)
|
||||
+ success = process_ext_session_bind(e);
|
||||
+ else
|
||||
+ debug("%s: unsupported extension \"%s\"", __func__, name);
|
||||
+send:
|
||||
+ send_status(e, success);
|
||||
+}
|
||||
/*
|
||||
* dispatch incoming message.
|
||||
* returns 1 on success, 0 for incomplete messages or -1 on error.
|
||||
@@ -1019,6 +1175,9 @@ process_message(u_int socknum)
|
||||
process_remove_smartcard_key(e);
|
||||
break;
|
||||
#endif /* ENABLE_PKCS11 */
|
||||
+ case SSH_AGENTC_EXTENSION:
|
||||
+ process_extension(e);
|
||||
+ break;
|
||||
default:
|
||||
/* Unknown message. Respond with failure. */
|
||||
error("Unknown message %d", type);
|
||||
--
|
||||
2.41.0
|
||||
@@ -0,0 +1,120 @@
|
||||
From 4fe3d0fbd3d6dc1f19354e0d73a3231c461ed044 Mon Sep 17 00:00:00 2001
|
||||
From: "djm@openbsd.org" <djm@openbsd.org>
|
||||
Date: Wed, 19 Jul 2023 13:56:33 +0000
|
||||
Subject: [PATCH 12/12] upstream: Disallow remote addition of FIDO/PKCS11
|
||||
provider libraries to ssh-agent by default.
|
||||
|
||||
The old behaviour of allowing remote clients from loading providers
|
||||
can be restored using `ssh-agent -O allow-remote-pkcs11`.
|
||||
|
||||
Detection of local/remote clients requires a ssh(1) that supports
|
||||
the `session-bind@openssh.com` extension. Forwarding access to a
|
||||
ssh-agent socket using non-OpenSSH tools may circumvent this control.
|
||||
|
||||
ok markus@
|
||||
|
||||
OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1f2731f5d7a8f8a8385c6031667ed29072c0d92a]
|
||||
CVE: CVE-2023-38408
|
||||
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
|
||||
---
|
||||
ssh-agent.1 | 20 ++++++++++++++++++++
|
||||
ssh-agent.c | 26 ++++++++++++++++++++++++--
|
||||
2 files changed, 44 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ssh-agent.1 b/ssh-agent.1
|
||||
index fff0db6..a0f1e21 100644
|
||||
--- a/ssh-agent.1
|
||||
+++ b/ssh-agent.1
|
||||
@@ -97,6 +97,26 @@ The default is
|
||||
Kill the current agent (given by the
|
||||
.Ev SSH_AGENT_PID
|
||||
environment variable).
|
||||
+Currently two options are supported:
|
||||
+.Cm allow-remote-pkcs11
|
||||
+and
|
||||
+.Pp
|
||||
+The
|
||||
+.Cm allow-remote-pkcs11
|
||||
+option allows clients of a forwarded
|
||||
+.Nm
|
||||
+to load PKCS#11 or FIDO provider libraries.
|
||||
+By default only local clients may perform this operation.
|
||||
+Note that signalling that a
|
||||
+.Nm
|
||||
+client remote is performed by
|
||||
+.Xr ssh 1 ,
|
||||
+and use of other tools to forward access to the agent socket may circumvent
|
||||
+this restriction.
|
||||
+.Pp
|
||||
+The
|
||||
+.Cm no-restrict-websafe ,
|
||||
+instructs
|
||||
.It Fl P Ar provider_whitelist
|
||||
Specify a pattern-list of acceptable paths for PKCS#11 and FIDO authenticator
|
||||
shared libraries that may be used with the
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 01c7f2b..40c1b6b 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: ssh-agent.c,v 1.280 2021/12/19 22:09:23 djm Exp $ */
|
||||
+/* $OpenBSD: ssh-agent.c,v 1.300 2023/07/19 13:56:33 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@@ -167,6 +167,12 @@ char socket_dir[PATH_MAX];
|
||||
/* PKCS#11/Security key path whitelist */
|
||||
static char *provider_whitelist;
|
||||
|
||||
+/*
|
||||
+ * Allows PKCS11 providers or SK keys that use non-internal providers to
|
||||
+ * be added over a remote connection (identified by session-bind@openssh.com).
|
||||
+ */
|
||||
+static int remote_add_provider;
|
||||
+
|
||||
/* locking */
|
||||
#define LOCK_SIZE 32
|
||||
#define LOCK_SALT_SIZE 16
|
||||
@@ -736,6 +742,15 @@ process_add_identity(SocketEntry *e)
|
||||
if (strcasecmp(sk_provider, "internal") == 0) {
|
||||
debug("%s: internal provider", __func__);
|
||||
} else {
|
||||
+ if (e->nsession_ids != 0 && !remote_add_provider) {
|
||||
+ verbose("failed add of SK provider \"%.100s\": "
|
||||
+ "remote addition of providers is disabled",
|
||||
+ sk_provider);
|
||||
+ free(sk_provider);
|
||||
+ free(comment);
|
||||
+ sshkey_free(k);
|
||||
+ goto send;
|
||||
+ }
|
||||
if (realpath(sk_provider, canonical_provider) == NULL) {
|
||||
verbose("failed provider \"%.100s\": "
|
||||
"realpath: %s", sk_provider,
|
||||
@@ -901,6 +916,11 @@ process_add_smartcard_key(SocketEntry *e)
|
||||
goto send;
|
||||
}
|
||||
}
|
||||
+ if (e->nsession_ids != 0 && !remote_add_provider) {
|
||||
+ verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
|
||||
+ "providers is disabled", provider);
|
||||
+ goto send;
|
||||
+ }
|
||||
if (realpath(provider, canonical_provider) == NULL) {
|
||||
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
|
||||
provider, strerror(errno));
|
||||
@@ -1556,7 +1576,9 @@ main(int ac, char **av)
|
||||
break;
|
||||
case 'O':
|
||||
if (strcmp(optarg, "no-restrict-websafe") == 0)
|
||||
- restrict_websafe = 0;
|
||||
+ restrict_websafe = 0;
|
||||
+ else if (strcmp(optarg, "allow-remote-pkcs11") == 0)
|
||||
+ remote_add_provider = 1;
|
||||
else
|
||||
fatal("Unknown -O option");
|
||||
break;
|
||||
--
|
||||
2.41.0
|
||||
@@ -27,6 +27,18 @@ SRC_URI = "http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.tar
|
||||
file://CVE-2020-14145.patch \
|
||||
file://CVE-2021-28041.patch \
|
||||
file://CVE-2021-41617.patch \
|
||||
file://CVE-2023-38408-01.patch \
|
||||
file://CVE-2023-38408-02.patch \
|
||||
file://CVE-2023-38408-03.patch \
|
||||
file://CVE-2023-38408-04.patch \
|
||||
file://CVE-2023-38408-05.patch \
|
||||
file://CVE-2023-38408-06.patch \
|
||||
file://CVE-2023-38408-07.patch \
|
||||
file://CVE-2023-38408-08.patch \
|
||||
file://CVE-2023-38408-09.patch \
|
||||
file://CVE-2023-38408-10.patch \
|
||||
file://CVE-2023-38408-11.patch \
|
||||
file://CVE-2023-38408-12.patch \
|
||||
"
|
||||
SRC_URI[md5sum] = "3076e6413e8dbe56d33848c1054ac091"
|
||||
SRC_URI[sha256sum] = "43925151e6cf6cee1450190c0e9af4dc36b41c12737619edff8bcebdff64e671"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
From 326909baf81a638d51fa8be1d8227518784f5cc4 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Kanavin <alex@linutronix.de>
|
||||
Date: Tue, 14 Sep 2021 12:18:25 +0200
|
||||
Subject: [PATCH] Configure: do not tweak mips cflags
|
||||
|
||||
This conflicts with mips machine definitons from yocto,
|
||||
e.g.
|
||||
| Error: -mips3 conflicts with the other architecture options, which imply -mips64r2
|
||||
|
||||
Upstream-Status: Inappropriate [oe-core specific]
|
||||
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
Configure | 10 ----------
|
||||
1 file changed, 10 deletions(-)
|
||||
|
||||
Index: openssl-3.0.4/Configure
|
||||
===================================================================
|
||||
--- openssl-3.0.4.orig/Configure
|
||||
+++ openssl-3.0.4/Configure
|
||||
@@ -1243,16 +1243,6 @@ if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
|
||||
push @{$config{shared_ldflag}}, "-mno-cygwin";
|
||||
}
|
||||
|
||||
-if ($target =~ /linux.*-mips/ && !$disabled{asm}
|
||||
- && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
|
||||
- # minimally required architecture flags for assembly modules
|
||||
- my $value;
|
||||
- $value = '-mips2' if ($target =~ /mips32/);
|
||||
- $value = '-mips3' if ($target =~ /mips64/);
|
||||
- unshift @{$config{cflags}}, $value;
|
||||
- unshift @{$config{cxxflags}}, $value if $config{CXX};
|
||||
-}
|
||||
-
|
||||
# If threads aren't disabled, check how possible they are
|
||||
unless ($disabled{threads}) {
|
||||
if ($auto_threads) {
|
||||
@@ -1,226 +0,0 @@
|
||||
From 879f7080d7e141f415c79eaa3a8ac4a3dad0348b Mon Sep 17 00:00:00 2001
|
||||
From: Pauli <pauli@openssl.org>
|
||||
Date: Wed, 8 Mar 2023 15:28:20 +1100
|
||||
Subject: [PATCH] x509: excessive resource use verifying policy constraints
|
||||
|
||||
A security vulnerability has been identified in all supported versions
|
||||
of OpenSSL related to the verification of X.509 certificate chains
|
||||
that include policy constraints. Attackers may be able to exploit this
|
||||
vulnerability by creating a malicious certificate chain that triggers
|
||||
exponential use of computational resources, leading to a denial-of-service
|
||||
(DoS) attack on affected systems.
|
||||
|
||||
Fixes CVE-2023-0464
|
||||
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20569)
|
||||
|
||||
CVE: CVE-2023-0464
|
||||
Upstream-Status: Backport [https://git.openssl.org/gitweb/?p=openssl.git;a=patch;h=879f7080d7e141f415c79eaa3a8ac4a3dad0348b]
|
||||
Signed-off-by: Nikhil R <nikhil.r@kpit.com>
|
||||
|
||||
---
|
||||
crypto/x509v3/pcy_local.h | 8 +++++++-
|
||||
crypto/x509v3/pcy_node.c | 12 +++++++++---
|
||||
crypto/x509v3/pcy_tree.c | 37 +++++++++++++++++++++++++++----------
|
||||
3 files changed, 43 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/crypto/x509v3/pcy_local.h b/crypto/x509v3/pcy_local.h
|
||||
index 5daf78de45..344aa06765 100644
|
||||
--- a/crypto/x509v3/pcy_local.h
|
||||
+++ b/crypto/x509v3/pcy_local.h
|
||||
@@ -111,6 +111,11 @@ struct X509_POLICY_LEVEL_st {
|
||||
};
|
||||
|
||||
struct X509_POLICY_TREE_st {
|
||||
+ /* The number of nodes in the tree */
|
||||
+ size_t node_count;
|
||||
+ /* The maximum number of nodes in the tree */
|
||||
+ size_t node_maximum;
|
||||
+
|
||||
/* This is the tree 'level' data */
|
||||
X509_POLICY_LEVEL *levels;
|
||||
int nlevel;
|
||||
@@ -159,7 +164,8 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
|
||||
X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
|
||||
X509_POLICY_DATA *data,
|
||||
X509_POLICY_NODE *parent,
|
||||
- X509_POLICY_TREE *tree);
|
||||
+ X509_POLICY_TREE *tree,
|
||||
+ int extra_data);
|
||||
void policy_node_free(X509_POLICY_NODE *node);
|
||||
int policy_node_match(const X509_POLICY_LEVEL *lvl,
|
||||
const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
|
||||
diff --git a/crypto/x509v3/pcy_node.c b/crypto/x509v3/pcy_node.c
|
||||
index e2d7b15322..d574fb9d66 100644
|
||||
--- a/crypto/x509v3/pcy_node.c
|
||||
+++ b/crypto/x509v3/pcy_node.c
|
||||
@@ -59,10 +59,15 @@ X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
|
||||
X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
|
||||
X509_POLICY_DATA *data,
|
||||
X509_POLICY_NODE *parent,
|
||||
- X509_POLICY_TREE *tree)
|
||||
+ X509_POLICY_TREE *tree,
|
||||
+ int extra_data)
|
||||
{
|
||||
X509_POLICY_NODE *node;
|
||||
|
||||
+ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */
|
||||
+ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum)
|
||||
+ return NULL;
|
||||
+
|
||||
node = OPENSSL_zalloc(sizeof(*node));
|
||||
if (node == NULL) {
|
||||
X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE);
|
||||
@@ -70,7 +75,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
|
||||
}
|
||||
node->data = data;
|
||||
node->parent = parent;
|
||||
- if (level) {
|
||||
+ if (level != NULL) {
|
||||
if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
|
||||
if (level->anyPolicy)
|
||||
goto node_error;
|
||||
@@ -90,7 +95,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
|
||||
}
|
||||
}
|
||||
|
||||
- if (tree) {
|
||||
+ if (extra_data) {
|
||||
if (tree->extra_data == NULL)
|
||||
tree->extra_data = sk_X509_POLICY_DATA_new_null();
|
||||
if (tree->extra_data == NULL){
|
||||
@@ -103,6 +108,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
|
||||
}
|
||||
}
|
||||
|
||||
+ tree->node_count++;
|
||||
if (parent)
|
||||
parent->nchild++;
|
||||
|
||||
diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c
|
||||
index 6e8322cbc5..6c7fd35405 100644
|
||||
--- a/crypto/x509v3/pcy_tree.c
|
||||
+++ b/crypto/x509v3/pcy_tree.c
|
||||
@@ -13,6 +13,18 @@
|
||||
|
||||
#include "pcy_local.h"
|
||||
|
||||
+/*
|
||||
+ * If the maximum number of nodes in the policy tree isn't defined, set it to
|
||||
+ * a generous default of 1000 nodes.
|
||||
+ *
|
||||
+ * Defining this to be zero means unlimited policy tree growth which opens the
|
||||
+ * door on CVE-2023-0464.
|
||||
+ */
|
||||
+
|
||||
+#ifndef OPENSSL_POLICY_TREE_NODES_MAX
|
||||
+# define OPENSSL_POLICY_TREE_NODES_MAX 1000
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Enable this to print out the complete policy tree at various point during
|
||||
* evaluation.
|
||||
@@ -168,6 +180,9 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
}
|
||||
|
||||
+ /* Limit the growth of the tree to mitigate CVE-2023-0464 */
|
||||
+ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX;
|
||||
+
|
||||
/*
|
||||
* http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3.
|
||||
*
|
||||
@@ -184,7 +199,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
|
||||
level = tree->levels;
|
||||
if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL)
|
||||
goto bad_tree;
|
||||
- if (level_add_node(level, data, NULL, tree) == NULL) {
|
||||
+ if (level_add_node(level, data, NULL, tree, 1) == NULL) {
|
||||
policy_data_free(data);
|
||||
goto bad_tree;
|
||||
}
|
||||
@@ -243,7 +258,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
|
||||
* Return value: 1 on success, 0 otherwise
|
||||
*/
|
||||
static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
|
||||
- X509_POLICY_DATA *data)
|
||||
+ X509_POLICY_DATA *data,
|
||||
+ X509_POLICY_TREE *tree)
|
||||
{
|
||||
X509_POLICY_LEVEL *last = curr - 1;
|
||||
int i, matched = 0;
|
||||
@@ -253,13 +269,13 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
|
||||
X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i);
|
||||
|
||||
if (policy_node_match(last, node, data->valid_policy)) {
|
||||
- if (level_add_node(curr, data, node, NULL) == NULL)
|
||||
+ if (level_add_node(curr, data, node, tree, 0) == NULL)
|
||||
return 0;
|
||||
matched = 1;
|
||||
}
|
||||
}
|
||||
if (!matched && last->anyPolicy) {
|
||||
- if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL)
|
||||
+ if (level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -272,7 +288,8 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
|
||||
* Return value: 1 on success, 0 otherwise.
|
||||
*/
|
||||
static int tree_link_nodes(X509_POLICY_LEVEL *curr,
|
||||
- const X509_POLICY_CACHE *cache)
|
||||
+ const X509_POLICY_CACHE *cache,
|
||||
+ X509_POLICY_TREE *tree)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -280,7 +297,7 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr,
|
||||
X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i);
|
||||
|
||||
/* Look for matching nodes in previous level */
|
||||
- if (!tree_link_matching_nodes(curr, data))
|
||||
+ if (!tree_link_matching_nodes(curr, data, tree))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -311,7 +328,7 @@ static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
|
||||
/* Curr may not have anyPolicy */
|
||||
data->qualifier_set = cache->anyPolicy->qualifier_set;
|
||||
data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
|
||||
- if (level_add_node(curr, data, node, tree) == NULL) {
|
||||
+ if (level_add_node(curr, data, node, tree, 1) == NULL) {
|
||||
policy_data_free(data);
|
||||
return 0;
|
||||
}
|
||||
@@ -373,7 +390,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr,
|
||||
}
|
||||
/* Finally add link to anyPolicy */
|
||||
if (last->anyPolicy &&
|
||||
- level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL)
|
||||
+ level_add_node(curr, cache->anyPolicy, last->anyPolicy, tree, 0) == NULL)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -555,7 +572,7 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree,
|
||||
extra->qualifier_set = anyPolicy->data->qualifier_set;
|
||||
extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
|
||||
| POLICY_DATA_FLAG_EXTRA_NODE;
|
||||
- node = level_add_node(NULL, extra, anyPolicy->parent, tree);
|
||||
+ node = level_add_node(NULL, extra, anyPolicy->parent, tree, 1);
|
||||
}
|
||||
if (!tree->user_policies) {
|
||||
tree->user_policies = sk_X509_POLICY_NODE_new_null();
|
||||
@@ -582,7 +599,7 @@ static int tree_evaluate(X509_POLICY_TREE *tree)
|
||||
|
||||
for (i = 1; i < tree->nlevel; i++, curr++) {
|
||||
cache = policy_cache_set(curr->cert);
|
||||
- if (!tree_link_nodes(curr, cache))
|
||||
+ if (!tree_link_nodes(curr, cache, tree))
|
||||
return X509_PCY_TREE_INTERNAL;
|
||||
|
||||
if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
|
||||
--
|
||||
2.34.1
|
||||
@@ -1,60 +0,0 @@
|
||||
From b013765abfa80036dc779dd0e50602c57bb3bf95 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Caswell <matt@openssl.org>
|
||||
Date: Tue, 7 Mar 2023 16:52:55 +0000
|
||||
Subject: [PATCH] Ensure that EXFLAG_INVALID_POLICY is checked even in leaf
|
||||
certs
|
||||
|
||||
Even though we check the leaf cert to confirm it is valid, we
|
||||
later ignored the invalid flag and did not notice that the leaf
|
||||
cert was bad.
|
||||
|
||||
Fixes: CVE-2023-0465
|
||||
|
||||
Reviewed-by: Hugo Landau <hlandau@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20588)
|
||||
|
||||
CVE: CVE-2023-0465
|
||||
Upstream-Status: Backport [https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=b013765abfa80036dc779dd0e50602c57bb3bf95]
|
||||
Comment: Refreshed first hunk
|
||||
Signed-off-by: Omkar Patil <omkar.patil@kpit.com>
|
||||
|
||||
---
|
||||
crypto/x509/x509_vfy.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
|
||||
index 925fbb5412..1dfe4f9f31 100644
|
||||
--- a/crypto/x509/x509_vfy.c
|
||||
+++ b/crypto/x509/x509_vfy.c
|
||||
@@ -1649,18 +1649,25 @@
|
||||
}
|
||||
/* Invalid or inconsistent extensions */
|
||||
if (ret == X509_PCY_TREE_INVALID) {
|
||||
- int i;
|
||||
+ int i, cbcalled = 0;
|
||||
|
||||
/* Locate certificates with bad extensions and notify callback. */
|
||||
- for (i = 1; i < sk_X509_num(ctx->chain); i++) {
|
||||
+ for (i = 0; i < sk_X509_num(ctx->chain); i++) {
|
||||
X509 *x = sk_X509_value(ctx->chain, i);
|
||||
|
||||
if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
|
||||
continue;
|
||||
+ cbcalled = 1;
|
||||
if (!verify_cb_cert(ctx, x, i,
|
||||
X509_V_ERR_INVALID_POLICY_EXTENSION))
|
||||
return 0;
|
||||
}
|
||||
+ if (!cbcalled) {
|
||||
+ /* Should not be able to get here */
|
||||
+ X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ /* The callback ignored the error so we return success */
|
||||
return 1;
|
||||
}
|
||||
if (ret == X509_PCY_TREE_FAILURE) {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
From 0d16b7e99aafc0b4a6d729eec65a411a7e025f0a Mon Sep 17 00:00:00 2001
|
||||
From: Tomas Mraz <tomas@openssl.org>
|
||||
Date: Tue, 21 Mar 2023 16:15:47 +0100
|
||||
Subject: [PATCH] Fix documentation of X509_VERIFY_PARAM_add0_policy()
|
||||
|
||||
The function was incorrectly documented as enabling policy checking.
|
||||
|
||||
Fixes: CVE-2023-0466
|
||||
|
||||
Reviewed-by: Matt Caswell <matt@openssl.org>
|
||||
Reviewed-by: Paul Dale <pauli@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/20564)
|
||||
|
||||
CVE: CVE-2023-0466
|
||||
Upstream-Status: Backport [https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff;h=0d16b7e99aafc0b4a6d729eec65a411a7e025f0a]
|
||||
Comment: Refreshed first hunk from CHANGE and NEWS
|
||||
Signed-off-by: Omkar Patil <omkar.patil@kpit.com>
|
||||
|
||||
---
|
||||
CHANGES | 5 +++++
|
||||
NEWS | 1 +
|
||||
doc/man3/X509_VERIFY_PARAM_set_flags.pod | 9 +++++++--
|
||||
3 files changed, 13 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/CHANGES b/CHANGES
|
||||
index efccf7838e..b19f1429bb 100644
|
||||
--- a/CHANGES
|
||||
+++ b/CHANGES
|
||||
@@ -9,6 +9,11 @@
|
||||
|
||||
Changes between 1.1.1s and 1.1.1t [7 Feb 2023]
|
||||
|
||||
+ *) Corrected documentation of X509_VERIFY_PARAM_add0_policy() to mention
|
||||
+ that it does not enable policy checking. Thanks to
|
||||
+ David Benjamin for discovering this issue. (CVE-2023-0466)
|
||||
+ [Tomas Mraz]
|
||||
+
|
||||
*) Fixed X.400 address type confusion in X.509 GeneralName.
|
||||
|
||||
There is a type confusion vulnerability relating to X.400 address processing
|
||||
diff --git a/NEWS b/NEWS
|
||||
index 36a9bb6890..62615693fa 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
Major changes between OpenSSL 1.1.1s and OpenSSL 1.1.1t [7 Feb 2023]
|
||||
|
||||
+ o Fixed documentation of X509_VERIFY_PARAM_add0_policy() (CVE-2023-0466)
|
||||
o Fixed X.400 address type confusion in X.509 GeneralName (CVE-2023-0286)
|
||||
o Fixed Use-after-free following BIO_new_NDEF (CVE-2023-0215)
|
||||
o Fixed Double free after calling PEM_read_bio_ex (CVE-2022-4450)
|
||||
diff --git a/doc/man3/X509_VERIFY_PARAM_set_flags.pod b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
|
||||
index f6f304bf7b..aa292f9336 100644
|
||||
--- a/doc/man3/X509_VERIFY_PARAM_set_flags.pod
|
||||
+++ b/doc/man3/X509_VERIFY_PARAM_set_flags.pod
|
||||
@@ -92,8 +92,9 @@ B<trust>.
|
||||
X509_VERIFY_PARAM_set_time() sets the verification time in B<param> to
|
||||
B<t>. Normally the current time is used.
|
||||
|
||||
-X509_VERIFY_PARAM_add0_policy() enables policy checking (it is disabled
|
||||
-by default) and adds B<policy> to the acceptable policy set.
|
||||
+X509_VERIFY_PARAM_add0_policy() adds B<policy> to the acceptable policy set.
|
||||
+Contrary to preexisting documentation of this function it does not enable
|
||||
+policy checking.
|
||||
|
||||
X509_VERIFY_PARAM_set1_policies() enables policy checking (it is disabled
|
||||
by default) and sets the acceptable policy set to B<policies>. Any existing
|
||||
@@ -377,6 +378,10 @@ and has no effect.
|
||||
|
||||
The X509_VERIFY_PARAM_get_hostflags() function was added in OpenSSL 1.1.0i.
|
||||
|
||||
+The function X509_VERIFY_PARAM_add0_policy() was historically documented as
|
||||
+enabling policy checking however the implementation has never done this.
|
||||
+The documentation was changed to align with the implementation.
|
||||
+
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
From 9e209944b35cf82368071f160a744b6178f9b098 Mon Sep 17 00:00:00 2001
|
||||
From: Richard Levitte <levitte@openssl.org>
|
||||
Date: Fri, 12 May 2023 10:00:13 +0200
|
||||
Subject: [PATCH] Restrict the size of OBJECT IDENTIFIERs that OBJ_obj2txt will
|
||||
translate
|
||||
|
||||
OBJ_obj2txt() would translate any size OBJECT IDENTIFIER to canonical
|
||||
numeric text form. For gigantic sub-identifiers, this would take a very
|
||||
long time, the time complexity being O(n^2) where n is the size of that
|
||||
sub-identifier.
|
||||
|
||||
To mitigate this, a restriction on the size that OBJ_obj2txt() will
|
||||
translate to canonical numeric text form is added, based on RFC 2578
|
||||
(STD 58), which says this:
|
||||
|
||||
> 3.5. OBJECT IDENTIFIER values
|
||||
>
|
||||
> An OBJECT IDENTIFIER value is an ordered list of non-negative numbers.
|
||||
> For the SMIv2, each number in the list is referred to as a sub-identifier,
|
||||
> there are at most 128 sub-identifiers in a value, and each sub-identifier
|
||||
> has a maximum value of 2^32-1 (4294967295 decimal).
|
||||
|
||||
Fixes otc/security#96
|
||||
Fixes CVE-2023-2650
|
||||
|
||||
Reviewed-by: Matt Caswell <matt@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/openssl/openssl/commit/9e209944b35cf82368071f160a744b6178f9b098]
|
||||
CVE: CVE-2023-2650
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
CHANGES | 28 +++++++++++++++++++++++++++-
|
||||
NEWS | 2 ++
|
||||
crypto/objects/obj_dat.c | 19 +++++++++++++++++++
|
||||
3 files changed, 48 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/CHANGES b/CHANGES
|
||||
index 1eaaf4e..f2cf38f 100644
|
||||
--- a/CHANGES
|
||||
+++ b/CHANGES
|
||||
@@ -7,7 +7,33 @@
|
||||
https://github.com/openssl/openssl/commits/ and pick the appropriate
|
||||
release branch.
|
||||
|
||||
- Changes between 1.1.1s and 1.1.1t [7 Feb 2023]
|
||||
+ Changes between 1.1.1t and 1.1.1u [xx XXX xxxx]
|
||||
+
|
||||
+ *) Mitigate for the time it takes for `OBJ_obj2txt` to translate gigantic
|
||||
+ OBJECT IDENTIFIER sub-identifiers to canonical numeric text form.
|
||||
+
|
||||
+ OBJ_obj2txt() would translate any size OBJECT IDENTIFIER to canonical
|
||||
+ numeric text form. For gigantic sub-identifiers, this would take a very
|
||||
+ long time, the time complexity being O(n^2) where n is the size of that
|
||||
+ sub-identifier. (CVE-2023-2650)
|
||||
+
|
||||
+ To mitigitate this, `OBJ_obj2txt()` will only translate an OBJECT
|
||||
+ IDENTIFIER to canonical numeric text form if the size of that OBJECT
|
||||
+ IDENTIFIER is 586 bytes or less, and fail otherwise.
|
||||
+
|
||||
+ The basis for this restriction is RFC 2578 (STD 58), section 3.5. OBJECT
|
||||
+ IDENTIFIER values, which stipulates that OBJECT IDENTIFIERS may have at
|
||||
+ most 128 sub-identifiers, and that the maximum value that each sub-
|
||||
+ identifier may have is 2^32-1 (4294967295 decimal).
|
||||
+
|
||||
+ For each byte of every sub-identifier, only the 7 lower bits are part of
|
||||
+ the value, so the maximum amount of bytes that an OBJECT IDENTIFIER with
|
||||
+ these restrictions may occupy is 32 * 128 / 7, which is approximately 586
|
||||
+ bytes.
|
||||
+
|
||||
+ Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
|
||||
+
|
||||
+Changes between 1.1.1s and 1.1.1t [7 Feb 2023]
|
||||
|
||||
*) Corrected documentation of X509_VERIFY_PARAM_add0_policy() to mention
|
||||
that it does not enable policy checking. Thanks to
|
||||
diff --git a/NEWS b/NEWS
|
||||
index a86220a..41922c4 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
Major changes between OpenSSL 1.1.1s and OpenSSL 1.1.1t [7 Feb 2023]
|
||||
|
||||
+ o Mitigate for very slow `OBJ_obj2txt()` performance with gigantic
|
||||
+ OBJECT IDENTIFIER sub-identities. (CVE-2023-2650)
|
||||
o Fixed documentation of X509_VERIFY_PARAM_add0_policy() (CVE-2023-0466)
|
||||
o Fixed X.400 address type confusion in X.509 GeneralName (CVE-2023-0286)
|
||||
o Fixed Use-after-free following BIO_new_NDEF (CVE-2023-0215)
|
||||
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
|
||||
index 7e8de72..d699915 100644
|
||||
--- a/crypto/objects/obj_dat.c
|
||||
+++ b/crypto/objects/obj_dat.c
|
||||
@@ -428,6 +428,25 @@ int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
|
||||
first = 1;
|
||||
bl = NULL;
|
||||
|
||||
+ /*
|
||||
+ * RFC 2578 (STD 58) says this about OBJECT IDENTIFIERs:
|
||||
+ *
|
||||
+ * > 3.5. OBJECT IDENTIFIER values
|
||||
+ * >
|
||||
+ * > An OBJECT IDENTIFIER value is an ordered list of non-negative
|
||||
+ * > numbers. For the SMIv2, each number in the list is referred to as a
|
||||
+ * > sub-identifier, there are at most 128 sub-identifiers in a value,
|
||||
+ * > and each sub-identifier has a maximum value of 2^32-1 (4294967295
|
||||
+ * > decimal).
|
||||
+ *
|
||||
+ * So a legitimate OID according to this RFC is at most (32 * 128 / 7),
|
||||
+ * i.e. 586 bytes long.
|
||||
+ *
|
||||
+ * Ref: https://datatracker.ietf.org/doc/html/rfc2578#section-3.5
|
||||
+ */
|
||||
+ if (len > 586)
|
||||
+ goto err;
|
||||
+
|
||||
while (len > 0) {
|
||||
l = 0;
|
||||
use_bn = 0;
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@@ -19,17 +19,14 @@ SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz \
|
||||
file://reproducible.patch \
|
||||
file://reproducibility.patch \
|
||||
file://0001-Configure-add-2-missing-key-sorts.patch \
|
||||
file://CVE-2023-0464.patch \
|
||||
file://CVE-2023-0465.patch \
|
||||
file://CVE-2023-0466.patch \
|
||||
file://CVE-2023-2650.patch \
|
||||
file://0001-Configure-do-not-tweak-mips-cflags.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_class-nativesdk = " \
|
||||
file://environment.d-openssl.sh \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "8dee9b24bdb1dcbf0c3d1e9b02fb8f6bf22165e807f45adeb7c9677536859d3b"
|
||||
SRC_URI[sha256sum] = "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8"
|
||||
|
||||
inherit lib_package multilib_header multilib_script ptest
|
||||
MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash"
|
||||
@@ -11,7 +11,7 @@ AUTHOR = "Thomas Hood"
|
||||
HOMEPAGE = "http://packages.debian.org/resolvconf"
|
||||
RDEPENDS_${PN} = "bash"
|
||||
|
||||
SRC_URI = "git://salsa.debian.org/debian/resolvconf.git;protocol=https;branch=master \
|
||||
SRC_URI = "git://salsa.debian.org/debian/resolvconf.git;protocol=https;branch=unstable \
|
||||
file://fix-path-for-busybox.patch \
|
||||
file://99_resolvconf \
|
||||
"
|
||||
|
||||
82
meta/recipes-core/busybox/busybox/CVE-2022-48174.patch
Normal file
82
meta/recipes-core/busybox/busybox/CVE-2022-48174.patch
Normal file
@@ -0,0 +1,82 @@
|
||||
From c18ebf861528ef24958dd99a146482d2a40014c7 Mon Sep 17 00:00:00 2001
|
||||
From: Denys Vlasenko <vda.linux@googlemail.com>
|
||||
Date: Mon, 12 Jun 2023 17:48:47 +0200
|
||||
Subject: [PATCH] shell: avoid segfault on ${0::0/0~09J}. Closes 15216
|
||||
|
||||
function old new delta
|
||||
evaluate_string 1011 1053 +42
|
||||
|
||||
CVE: CVE-2022-48174
|
||||
Upstream-Status: Backport [d417193cf37ca1005830d7e16f5fa7e1d8a44209]
|
||||
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
|
||||
---
|
||||
shell/math.c | 39 +++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/shell/math.c b/shell/math.c
|
||||
index af1ab55c0..79824e81f 100644
|
||||
--- a/shell/math.c
|
||||
+++ b/shell/math.c
|
||||
@@ -578,6 +578,28 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+//TODO: much better estimation than expr_len/2? Such as:
|
||||
+//static unsigned estimate_nums_and_names(const char *expr)
|
||||
+//{
|
||||
+// unsigned count = 0;
|
||||
+// while (*(expr = skip_whitespace(expr)) != '\0') {
|
||||
+// const char *p;
|
||||
+// if (isdigit(*expr)) {
|
||||
+// while (isdigit(*++expr))
|
||||
+// continue;
|
||||
+// count++;
|
||||
+// continue;
|
||||
+// }
|
||||
+// p = endofname(expr);
|
||||
+// if (p != expr) {
|
||||
+// expr = p;
|
||||
+// count++;
|
||||
+// continue;
|
||||
+// }
|
||||
+// }
|
||||
+// return count;
|
||||
+//}
|
||||
+
|
||||
static arith_t FAST_FUNC
|
||||
evaluate_string(arith_state_t *math_state, const char *expr)
|
||||
{
|
||||
@@ -585,10 +607,12 @@ evaluate_string(arith_state_t *math_state, const char *expr)
|
||||
const char *errmsg;
|
||||
const char *start_expr = expr = skip_whitespace(expr);
|
||||
unsigned expr_len = strlen(expr) + 2;
|
||||
- /* Stack of integers */
|
||||
- /* The proof that there can be no more than strlen(startbuf)/2+1
|
||||
- * integers in any given correct or incorrect expression
|
||||
- * is left as an exercise to the reader. */
|
||||
+ /* Stack of integers/names */
|
||||
+ /* There can be no more than strlen(startbuf)/2+1
|
||||
+ * integers/names in any given correct or incorrect expression.
|
||||
+ * (modulo "09v09v09v09v09v" case,
|
||||
+ * but we have code to detect that early)
|
||||
+ */
|
||||
var_or_num_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
|
||||
var_or_num_t *numstackptr = numstack;
|
||||
/* Stack of operator tokens */
|
||||
@@ -657,6 +681,13 @@ evaluate_string(arith_state_t *math_state, const char *expr)
|
||||
numstackptr->var = NULL;
|
||||
errno = 0;
|
||||
numstackptr->val = strto_arith_t(expr, (char**) &expr);
|
||||
+ /* A number can't be followed by another number, or a variable name.
|
||||
+ * We'd catch this later anyway, but this would require numstack[]
|
||||
+ * to be twice as deep to handle strings where _every_ char is
|
||||
+ * a new number or name. Example: 09v09v09v09v09v09v09v09v09v
|
||||
+ */
|
||||
+ if (isalnum(*expr) || *expr == '_')
|
||||
+ goto err;
|
||||
if (errno)
|
||||
numstackptr->val = 0; /* bash compat */
|
||||
goto num;
|
||||
--
|
||||
2.40.1
|
||||
|
||||
@@ -55,6 +55,7 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
|
||||
file://CVE-2021-42374.patch \
|
||||
file://CVE-2021-42376.patch \
|
||||
file://CVE-2021-423xx-awk.patch \
|
||||
file://CVE-2022-48174.patch \
|
||||
file://0001-libbb-sockaddr2str-ensure-only-printable-characters-.patch \
|
||||
file://0002-nslookup-sanitize-all-printed-strings-with-printable.patch \
|
||||
"
|
||||
|
||||
@@ -8,6 +8,7 @@ SRC_URI = "https://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \
|
||||
file://tmpdir.patch \
|
||||
file://dbus-1.init \
|
||||
file://clear-guid_from_server-if-send_negotiate_unix_f.patch \
|
||||
file://CVE-2023-34969.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "bc42d196c1756ac520d61bf3ccd6f42013617def45dd1e591a6091abf51dca38"
|
||||
@@ -31,3 +32,5 @@ PACKAGECONFIG[systemd] = "--enable-systemd --with-systemdsystemunitdir=${systemd
|
||||
PACKAGECONFIG[x11] = "--with-x --enable-x11-autolaunch,--without-x --disable-x11-autolaunch, virtual/libx11 libsm"
|
||||
PACKAGECONFIG[user-session] = "--enable-user-session --with-systemduserunitdir=${systemd_user_unitdir},--disable-user-session"
|
||||
PACKAGECONFIG[verbose-mode] = "--enable-verbose-mode,,,"
|
||||
|
||||
CVE_PRODUCT += "d-bus_project:d-bus freedesktop:dbus freedesktop:libdbus"
|
||||
|
||||
96
meta/recipes-core/dbus/dbus/CVE-2023-34969.patch
Normal file
96
meta/recipes-core/dbus/dbus/CVE-2023-34969.patch
Normal file
@@ -0,0 +1,96 @@
|
||||
From 37a4dc5835731a1f7a81f1b67c45b8dfb556dd1c Mon Sep 17 00:00:00 2001
|
||||
From: hongjinghao <q1204531485@163.com>
|
||||
Date: Mon, 5 Jun 2023 18:17:06 +0100
|
||||
Subject: [PATCH] bus: Assign a serial number for messages from the driver
|
||||
|
||||
Normally, it's enough to rely on a message being given a serial number
|
||||
by the DBusConnection just before it is actually sent. However, in the
|
||||
rare case where the policy blocks the driver from sending a message
|
||||
(due to a deny rule or the outgoing message quota being full), we need
|
||||
to get a valid serial number sooner, so that we can copy it into the
|
||||
DBUS_HEADER_FIELD_REPLY_SERIAL field (which is mandatory) in the error
|
||||
message sent to monitors. Otherwise, the dbus-daemon will crash with
|
||||
an assertion failure if at least one Monitoring client is attached,
|
||||
because zero is not a valid serial number to copy.
|
||||
|
||||
This fixes a denial-of-service vulnerability: if a privileged user is
|
||||
monitoring the well-known system bus using a Monitoring client like
|
||||
dbus-monitor or `busctl monitor`, then an unprivileged user can cause
|
||||
denial-of-service by triggering this crash. A mitigation for this
|
||||
vulnerability is to avoid attaching Monitoring clients to the system
|
||||
bus when they are not needed. If there are no Monitoring clients, then
|
||||
the vulnerable code is not reached.
|
||||
|
||||
Co-authored-by: Simon McVittie <smcv@collabora.com>
|
||||
Resolves: dbus/dbus#457
|
||||
(cherry picked from commit b159849e031000d1dbc1ab876b5fc78a3ce9b534)
|
||||
---
|
||||
bus/connection.c | 15 +++++++++++++++
|
||||
dbus/dbus-connection-internal.h | 2 ++
|
||||
dbus/dbus-connection.c | 11 ++++++++++-
|
||||
3 files changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/bus/connection.c b/bus/connection.c
|
||||
index b3583433..215f0230 100644
|
||||
--- a/bus/connection.c
|
||||
+++ b/bus/connection.c
|
||||
@@ -2350,6 +2350,21 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
|
||||
if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
|
||||
return FALSE;
|
||||
|
||||
+ /* Make sure the message has a non-zero serial number, otherwise
|
||||
+ * bus_transaction_capture_error_reply() will not be able to mock up
|
||||
+ * a corresponding reply for it. Normally this would be delayed until
|
||||
+ * the first time we actually send the message out from a
|
||||
+ * connection, when the transaction is committed, but that's too late
|
||||
+ * in this case.
|
||||
+ */
|
||||
+ if (dbus_message_get_serial (message) == 0)
|
||||
+ {
|
||||
+ dbus_uint32_t next_serial;
|
||||
+
|
||||
+ next_serial = _dbus_connection_get_next_client_serial (connection);
|
||||
+ dbus_message_set_serial (message, next_serial);
|
||||
+ }
|
||||
+
|
||||
if (bus_connection_is_active (connection))
|
||||
{
|
||||
if (!dbus_message_set_destination (message,
|
||||
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
|
||||
index 48357321..ba79b192 100644
|
||||
--- a/dbus/dbus-connection-internal.h
|
||||
+++ b/dbus/dbus-connection-internal.h
|
||||
@@ -54,6 +54,8 @@ DBUS_PRIVATE_EXPORT
|
||||
DBusConnection * _dbus_connection_ref_unlocked (DBusConnection *connection);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
void _dbus_connection_unref_unlocked (DBusConnection *connection);
|
||||
+DBUS_PRIVATE_EXPORT
|
||||
+dbus_uint32_t _dbus_connection_get_next_client_serial (DBusConnection *connection);
|
||||
void _dbus_connection_queue_received_message_link (DBusConnection *connection,
|
||||
DBusList *link);
|
||||
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection);
|
||||
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
|
||||
index c525b6dc..09cef278 100644
|
||||
--- a/dbus/dbus-connection.c
|
||||
+++ b/dbus/dbus-connection.c
|
||||
@@ -1456,7 +1456,16 @@ _dbus_connection_unref_unlocked (DBusConnection *connection)
|
||||
_dbus_connection_last_unref (connection);
|
||||
}
|
||||
|
||||
-static dbus_uint32_t
|
||||
+/**
|
||||
+ * Allocate and return the next non-zero serial number for outgoing messages.
|
||||
+ *
|
||||
+ * This method is only valid to call from single-threaded code, such as
|
||||
+ * the dbus-daemon, or with the connection lock held.
|
||||
+ *
|
||||
+ * @param connection the connection
|
||||
+ * @returns A suitable serial number for the next message to be sent on the connection.
|
||||
+ */
|
||||
+dbus_uint32_t
|
||||
_dbus_connection_get_next_client_serial (DBusConnection *connection)
|
||||
{
|
||||
dbus_uint32_t serial;
|
||||
--
|
||||
2.25.1
|
||||
|
||||
290
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
Normal file
290
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-29499.patch
Normal file
@@ -0,0 +1,290 @@
|
||||
From 5f4485c4ff57fdefb1661531788def7ca5a47328 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 17 Aug 2023 04:19:44 +0000
|
||||
Subject: [PATCH] gvariant-serialiser: Check offset table entry size is minimal
|
||||
|
||||
The entries in an offset table (which is used for variable sized arrays
|
||||
and tuples containing variable sized members) are sized so that they can
|
||||
address every byte in the overall variant.
|
||||
|
||||
The specification requires that for a variant to be in normal form, its
|
||||
offset table entries must be the minimum width such that they can
|
||||
address every byte in the variant.
|
||||
|
||||
That minimality requirement was not checked in
|
||||
`g_variant_is_normal_form()`, leading to two different byte arrays being
|
||||
interpreted as the normal form of a given variant tree. That kind of
|
||||
confusion could potentially be exploited, and is certainly a bug.
|
||||
|
||||
Fix it by adding the necessary checks on offset table entry width, and
|
||||
unit tests.
|
||||
|
||||
Spotted by William Manley.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Fixes: #2794
|
||||
|
||||
CVE: CVE-2023-29499
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/5f4485c4ff57fdefb1661531788def7ca5a47328]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-serialiser.c | 19 +++-
|
||||
glib/tests/gvariant.c | 176 +++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 194 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index 0bf7243..5aa2cbc 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -694,6 +694,10 @@ gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
|
||||
out.data_size = last_end;
|
||||
out.array = value.data + last_end;
|
||||
out.length = offsets_array_size / out.offset_size;
|
||||
+
|
||||
+ if (out.length > 0 && gvs_calculate_total_size (last_end, out.length) != value.size)
|
||||
+ return out; /* offset size not minimal */
|
||||
+
|
||||
out.is_normal = TRUE;
|
||||
|
||||
return out;
|
||||
@@ -1201,6 +1205,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
gsize length;
|
||||
gsize offset;
|
||||
gsize i;
|
||||
+ gsize offset_table_size;
|
||||
|
||||
/* as per the comment in gvs_tuple_get_child() */
|
||||
if G_UNLIKELY (value.data == NULL && value.size != 0)
|
||||
@@ -1305,7 +1310,19 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
}
|
||||
}
|
||||
|
||||
- return offset_ptr == offset;
|
||||
+ /* @offset_ptr has been counting backwards from the end of the variant, to
|
||||
+ * find the beginning of the offset table. @offset has been counting forwards
|
||||
+ * from the beginning of the variant to find the end of the data. They should
|
||||
+ * have met in the middle. */
|
||||
+ if (offset_ptr != offset)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ offset_table_size = value.size - offset_ptr;
|
||||
+ if (value.size > 0 &&
|
||||
+ gvs_calculate_total_size (offset, offset_table_size / offset_size) != value.size)
|
||||
+ return FALSE; /* offset size not minimal */
|
||||
+
|
||||
+ return TRUE;
|
||||
}
|
||||
|
||||
/* Variants {{{2
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index d640c81..4ce0e4f 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -5092,6 +5092,86 @@ test_normal_checking_array_offsets2 (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
|
||||
+ * its offset table entries are too wide.
|
||||
+ *
|
||||
+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
|
||||
+static void
|
||||
+test_normal_checking_array_offsets_minimal_sized (void)
|
||||
+{
|
||||
+ GVariantBuilder builder;
|
||||
+ gsize i;
|
||||
+ GVariant *aay_constructed = NULL;
|
||||
+ const guint8 *data = NULL;
|
||||
+ guint8 *data_owned = NULL;
|
||||
+ GVariant *aay_deserialised = NULL;
|
||||
+ GVariant *aay_normalised = NULL;
|
||||
+
|
||||
+ /* Construct an array of type aay, consisting of 128 elements which are each
|
||||
+ * an empty array, i.e. `[[] * 128]`. This is chosen because the inner
|
||||
+ * elements are variable sized (making the outer array variable sized, so it
|
||||
+ * must have an offset table), but they are also zero-sized when serialised.
|
||||
+ * So the serialised representation of @aay_constructed consists entirely of
|
||||
+ * its offset table, which is entirely zeroes.
|
||||
+ *
|
||||
+ * The array is chosen to be 128 elements long because that means offset
|
||||
+ * table entries which are 1 byte long. If the elements in the array were
|
||||
+ * non-zero-sized (to the extent that the overall array is ≥256 bytes long),
|
||||
+ * the offset table entries would end up being 2 bytes long. */
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
|
||||
+
|
||||
+ for (i = 0; i < 128; i++)
|
||||
+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
|
||||
+
|
||||
+ aay_constructed = g_variant_builder_end (&builder);
|
||||
+
|
||||
+ /* Verify that the constructed array is in normal form, and its serialised
|
||||
+ * form is `b'\0' * 128`. */
|
||||
+ g_assert_true (g_variant_is_normal_form (aay_constructed));
|
||||
+ g_assert_cmpuint (g_variant_n_children (aay_constructed), ==, 128);
|
||||
+ g_assert_cmpuint (g_variant_get_size (aay_constructed), ==, 128);
|
||||
+
|
||||
+ data = g_variant_get_data (aay_constructed);
|
||||
+ for (i = 0; i < g_variant_get_size (aay_constructed); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ /* Construct a serialised `aay` GVariant which is `b'\0' * 256`. This has to
|
||||
+ * be a non-normal form of `[[] * 128]`, with 2-byte-long offset table
|
||||
+ * entries, because each offset table entry has to be able to reference all of
|
||||
+ * the byte boundaries in the container. All the entries in the offset table
|
||||
+ * are zero, so all the elements of the array are zero-sized. */
|
||||
+ data = data_owned = g_malloc0 (256);
|
||||
+ aay_deserialised = g_variant_new_from_data (G_VARIANT_TYPE ("aay"),
|
||||
+ data,
|
||||
+ 256,
|
||||
+ FALSE,
|
||||
+ g_free,
|
||||
+ g_steal_pointer (&data_owned));
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (aay_deserialised));
|
||||
+ g_assert_cmpuint (g_variant_n_children (aay_deserialised), ==, 128);
|
||||
+ g_assert_cmpuint (g_variant_get_size (aay_deserialised), ==, 256);
|
||||
+
|
||||
+ data = g_variant_get_data (aay_deserialised);
|
||||
+ for (i = 0; i < g_variant_get_size (aay_deserialised); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ /* Get its normal form. That should change the serialised size. */
|
||||
+ aay_normalised = g_variant_get_normal_form (aay_deserialised);
|
||||
+
|
||||
+ g_assert_true (g_variant_is_normal_form (aay_normalised));
|
||||
+ g_assert_cmpuint (g_variant_n_children (aay_normalised), ==, 128);
|
||||
+ g_assert_cmpuint (g_variant_get_size (aay_normalised), ==, 128);
|
||||
+
|
||||
+ data = g_variant_get_data (aay_normalised);
|
||||
+ for (i = 0; i < g_variant_get_size (aay_normalised); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ g_variant_unref (aay_normalised);
|
||||
+ g_variant_unref (aay_deserialised);
|
||||
+ g_variant_unref (aay_constructed);
|
||||
+}
|
||||
+
|
||||
/* Test that a tuple with invalidly large values in its offset table is
|
||||
* normalised successfully without looping infinitely. */
|
||||
static void
|
||||
@@ -5286,6 +5366,98 @@ test_normal_checking_tuple_offsets4 (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* Test that an otherwise-valid serialised GVariant is considered non-normal if
|
||||
+ * its offset table entries are too wide.
|
||||
+ *
|
||||
+ * See §2.3.6 (Framing Offsets) of the GVariant specification. */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets_minimal_sized (void)
|
||||
+{
|
||||
+ GString *type_string = NULL;
|
||||
+ GVariantBuilder builder;
|
||||
+ gsize i;
|
||||
+ GVariant *ray_constructed = NULL;
|
||||
+ const guint8 *data = NULL;
|
||||
+ guint8 *data_owned = NULL;
|
||||
+ GVariant *ray_deserialised = NULL;
|
||||
+ GVariant *ray_normalised = NULL;
|
||||
+
|
||||
+ /* Construct a tuple of type (ay…ay), consisting of 129 members which are each
|
||||
+ * an empty array, i.e. `([] * 129)`. This is chosen because the inner
|
||||
+ * members are variable sized, so the outer tuple must have an offset table,
|
||||
+ * but they are also zero-sized when serialised. So the serialised
|
||||
+ * representation of @ray_constructed consists entirely of its offset table,
|
||||
+ * which is entirely zeroes.
|
||||
+ *
|
||||
+ * The tuple is chosen to be 129 members long because that means it has 128
|
||||
+ * offset table entries which are 1 byte long each. If the members in the
|
||||
+ * tuple were non-zero-sized (to the extent that the overall tuple is ≥256
|
||||
+ * bytes long), the offset table entries would end up being 2 bytes long.
|
||||
+ *
|
||||
+ * 129 members are used unlike 128 array elements in
|
||||
+ * test_normal_checking_array_offsets_minimal_sized(), because the last member
|
||||
+ * in a tuple never needs an offset table entry. */
|
||||
+ type_string = g_string_new ("");
|
||||
+ g_string_append_c (type_string, '(');
|
||||
+ for (i = 0; i < 129; i++)
|
||||
+ g_string_append (type_string, "ay");
|
||||
+ g_string_append_c (type_string, ')');
|
||||
+
|
||||
+ g_variant_builder_init (&builder, G_VARIANT_TYPE (type_string->str));
|
||||
+
|
||||
+ for (i = 0; i < 129; i++)
|
||||
+ g_variant_builder_add_value (&builder, g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0));
|
||||
+
|
||||
+ ray_constructed = g_variant_builder_end (&builder);
|
||||
+
|
||||
+ /* Verify that the constructed tuple is in normal form, and its serialised
|
||||
+ * form is `b'\0' * 128`. */
|
||||
+ g_assert_true (g_variant_is_normal_form (ray_constructed));
|
||||
+ g_assert_cmpuint (g_variant_n_children (ray_constructed), ==, 129);
|
||||
+ g_assert_cmpuint (g_variant_get_size (ray_constructed), ==, 128);
|
||||
+
|
||||
+ data = g_variant_get_data (ray_constructed);
|
||||
+ for (i = 0; i < g_variant_get_size (ray_constructed); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ /* Construct a serialised `(ay…ay)` GVariant which is `b'\0' * 256`. This has
|
||||
+ * to be a non-normal form of `([] * 129)`, with 2-byte-long offset table
|
||||
+ * entries, because each offset table entry has to be able to reference all of
|
||||
+ * the byte boundaries in the container. All the entries in the offset table
|
||||
+ * are zero, so all the members of the tuple are zero-sized. */
|
||||
+ data = data_owned = g_malloc0 (256);
|
||||
+ ray_deserialised = g_variant_new_from_data (G_VARIANT_TYPE (type_string->str),
|
||||
+ data,
|
||||
+ 256,
|
||||
+ FALSE,
|
||||
+ g_free,
|
||||
+ g_steal_pointer (&data_owned));
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (ray_deserialised));
|
||||
+ g_assert_cmpuint (g_variant_n_children (ray_deserialised), ==, 129);
|
||||
+ g_assert_cmpuint (g_variant_get_size (ray_deserialised), ==, 256);
|
||||
+
|
||||
+ data = g_variant_get_data (ray_deserialised);
|
||||
+ for (i = 0; i < g_variant_get_size (ray_deserialised); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ /* Get its normal form. That should change the serialised size. */
|
||||
+ ray_normalised = g_variant_get_normal_form (ray_deserialised);
|
||||
+
|
||||
+ g_assert_true (g_variant_is_normal_form (ray_normalised));
|
||||
+ g_assert_cmpuint (g_variant_n_children (ray_normalised), ==, 129);
|
||||
+ g_assert_cmpuint (g_variant_get_size (ray_normalised), ==, 128);
|
||||
+
|
||||
+ data = g_variant_get_data (ray_normalised);
|
||||
+ for (i = 0; i < g_variant_get_size (ray_normalised); i++)
|
||||
+ g_assert_cmpuint (data[i], ==, 0);
|
||||
+
|
||||
+ g_variant_unref (ray_normalised);
|
||||
+ g_variant_unref (ray_deserialised);
|
||||
+ g_variant_unref (ray_constructed);
|
||||
+ g_string_free (type_string, TRUE);
|
||||
+}
|
||||
+
|
||||
/* Test that an empty object path is normalised successfully to the base object
|
||||
* path, ‘/’. */
|
||||
static void
|
||||
@@ -5431,6 +5603,8 @@ main (int argc, char **argv)
|
||||
test_normal_checking_array_offsets);
|
||||
g_test_add_func ("/gvariant/normal-checking/array-offsets2",
|
||||
test_normal_checking_array_offsets2);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/array-offsets/minimal-sized",
|
||||
+ test_normal_checking_array_offsets_minimal_sized);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
|
||||
test_normal_checking_tuple_offsets);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
|
||||
@@ -5439,6 +5613,8 @@ main (int argc, char **argv)
|
||||
test_normal_checking_tuple_offsets3);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
|
||||
test_normal_checking_tuple_offsets4);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
|
||||
+ test_normal_checking_tuple_offsets_minimal_sized);
|
||||
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
|
||||
test_normal_checking_empty_object_path);
|
||||
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
|
||||
From: William Manley <will@stb-tester.com>
|
||||
Date: Wed, 9 Aug 2023 10:04:49 +0000
|
||||
Subject: [PATCH] gvariant-core: Consolidate construction of
|
||||
`GVariantSerialised`
|
||||
|
||||
So I only need to change it in one place.
|
||||
|
||||
This introduces no functional changes.
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant.c | 8 +++++---
|
||||
glib/tests/gvariant.c | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index 8ba701e..4dbd9e8 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5952,14 +5952,16 @@ g_variant_byteswap (GVariant *value)
|
||||
g_variant_serialised_byteswap (serialised);
|
||||
|
||||
bytes = g_bytes_new_take (serialised.data, serialised.size);
|
||||
- new = g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE);
|
||||
+ new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
/* contains no multi-byte data */
|
||||
- new = value;
|
||||
+ new = g_variant_get_normal_form (value);
|
||||
|
||||
- return g_variant_ref_sink (new);
|
||||
+ g_assert (g_variant_is_trusted (new));
|
||||
+
|
||||
+ return g_steal_pointer (&new);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 4ce0e4f..3dda08e 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -3834,6 +3834,29 @@ test_gv_byteswap (void)
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
+static void
|
||||
+test_gv_byteswap_non_normal_non_aligned (void)
|
||||
+{
|
||||
+ const guint8 data[] = { 0x02 };
|
||||
+ GVariant *v = NULL;
|
||||
+ GVariant *v_byteswapped = NULL;
|
||||
+
|
||||
+ g_test_summary ("Test that calling g_variant_byteswap() on a variant which "
|
||||
+ "is in non-normal form and doesn’t need byteswapping returns "
|
||||
+ "the same variant in normal form.");
|
||||
+
|
||||
+ v = g_variant_new_from_data (G_VARIANT_TYPE_BOOLEAN, data, sizeof (data), FALSE, NULL, NULL);
|
||||
+ g_assert_false (g_variant_is_normal_form (v));
|
||||
+
|
||||
+ v_byteswapped = g_variant_byteswap (v);
|
||||
+ g_assert_true (g_variant_is_normal_form (v_byteswapped));
|
||||
+
|
||||
+ g_assert_cmpvariant (v, v_byteswapped);
|
||||
+
|
||||
+ g_variant_unref (v);
|
||||
+ g_variant_unref (v_byteswapped);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
test_parser (void)
|
||||
{
|
||||
@@ -5570,6 +5593,7 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/gvariant/builder-memory", test_builder_memory);
|
||||
g_test_add_func ("/gvariant/hashing", test_hashing);
|
||||
g_test_add_func ("/gvariant/byteswap", test_gv_byteswap);
|
||||
+ g_test_add_func ("/gvariant/byteswap/non-normal-non-aligned", test_gv_byteswap_non_normal_non_aligned);
|
||||
g_test_add_func ("/gvariant/parser", test_parses);
|
||||
g_test_add_func ("/gvariant/parser/integer-bounds", test_parser_integer_bounds);
|
||||
g_test_add_func ("/gvariant/parser/recursion", test_parser_recursion);
|
||||
--
|
||||
2.24.4
|
||||
|
||||
255
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
Normal file
255
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32611-0002.patch
Normal file
@@ -0,0 +1,255 @@
|
||||
From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
|
||||
From: William Manley <will@stb-tester.com>
|
||||
Date: Wed, 9 Aug 2023 10:39:34 +0000
|
||||
Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
|
||||
framing offsets
|
||||
|
||||
This introduces no functional changes.
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant.c | 81 +++++++++++++++++++++++++++++++++----------
|
||||
glib/tests/gvariant.c | 57 ++++++++++++++++++++++++++----
|
||||
2 files changed, 112 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index 4dbd9e8..a80c2c9 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5788,7 +5788,8 @@ g_variant_iter_loop (GVariantIter *iter,
|
||||
|
||||
/* Serialised data {{{1 */
|
||||
static GVariant *
|
||||
-g_variant_deep_copy (GVariant *value)
|
||||
+g_variant_deep_copy (GVariant *value,
|
||||
+ gboolean byteswap)
|
||||
{
|
||||
switch (g_variant_classify (value))
|
||||
{
|
||||
@@ -5806,7 +5807,7 @@ g_variant_deep_copy (GVariant *value)
|
||||
for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
|
||||
{
|
||||
GVariant *child = g_variant_get_child_value (value, i);
|
||||
- g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
|
||||
+ g_variant_builder_add_value (&builder, g_variant_deep_copy (child, byteswap));
|
||||
g_variant_unref (child);
|
||||
}
|
||||
|
||||
@@ -5820,28 +5821,63 @@ g_variant_deep_copy (GVariant *value)
|
||||
return g_variant_new_byte (g_variant_get_byte (value));
|
||||
|
||||
case G_VARIANT_CLASS_INT16:
|
||||
- return g_variant_new_int16 (g_variant_get_int16 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_int16 (GUINT16_SWAP_LE_BE (g_variant_get_int16 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_int16 (g_variant_get_int16 (value));
|
||||
|
||||
case G_VARIANT_CLASS_UINT16:
|
||||
- return g_variant_new_uint16 (g_variant_get_uint16 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_uint16 (GUINT16_SWAP_LE_BE (g_variant_get_uint16 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_uint16 (g_variant_get_uint16 (value));
|
||||
|
||||
case G_VARIANT_CLASS_INT32:
|
||||
- return g_variant_new_int32 (g_variant_get_int32 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_int32 (GUINT32_SWAP_LE_BE (g_variant_get_int32 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_int32 (g_variant_get_int32 (value));
|
||||
|
||||
case G_VARIANT_CLASS_UINT32:
|
||||
- return g_variant_new_uint32 (g_variant_get_uint32 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_uint32 (GUINT32_SWAP_LE_BE (g_variant_get_uint32 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_uint32 (g_variant_get_uint32 (value));
|
||||
|
||||
case G_VARIANT_CLASS_INT64:
|
||||
- return g_variant_new_int64 (g_variant_get_int64 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_int64 (GUINT64_SWAP_LE_BE (g_variant_get_int64 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_int64 (g_variant_get_int64 (value));
|
||||
|
||||
case G_VARIANT_CLASS_UINT64:
|
||||
- return g_variant_new_uint64 (g_variant_get_uint64 (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_uint64 (GUINT64_SWAP_LE_BE (g_variant_get_uint64 (value)));
|
||||
+ else
|
||||
+ return g_variant_new_uint64 (g_variant_get_uint64 (value));
|
||||
|
||||
case G_VARIANT_CLASS_HANDLE:
|
||||
- return g_variant_new_handle (g_variant_get_handle (value));
|
||||
+ if (byteswap)
|
||||
+ return g_variant_new_handle (GUINT32_SWAP_LE_BE (g_variant_get_handle (value)));
|
||||
+ else
|
||||
+ return g_variant_new_handle (g_variant_get_handle (value));
|
||||
|
||||
case G_VARIANT_CLASS_DOUBLE:
|
||||
- return g_variant_new_double (g_variant_get_double (value));
|
||||
+ if (byteswap)
|
||||
+ {
|
||||
+ /* We have to convert the double to a uint64 here using a union,
|
||||
+ * because a cast will round it numerically. */
|
||||
+ union
|
||||
+ {
|
||||
+ guint64 u64;
|
||||
+ gdouble dbl;
|
||||
+ } u1, u2;
|
||||
+ u1.dbl = g_variant_get_double (value);
|
||||
+ u2.u64 = GUINT64_SWAP_LE_BE (u1.u64);
|
||||
+ return g_variant_new_double (u2.dbl);
|
||||
+ }
|
||||
+ else
|
||||
+ return g_variant_new_double (g_variant_get_double (value));
|
||||
|
||||
case G_VARIANT_CLASS_STRING:
|
||||
return g_variant_new_string (g_variant_get_string (value, NULL));
|
||||
@@ -5896,7 +5932,7 @@ g_variant_get_normal_form (GVariant *value)
|
||||
if (g_variant_is_normal_form (value))
|
||||
return g_variant_ref (value);
|
||||
|
||||
- trusted = g_variant_deep_copy (value);
|
||||
+ trusted = g_variant_deep_copy (value, FALSE);
|
||||
g_assert (g_variant_is_trusted (trusted));
|
||||
|
||||
return g_variant_ref_sink (trusted);
|
||||
@@ -5916,6 +5952,11 @@ g_variant_get_normal_form (GVariant *value)
|
||||
* contain multi-byte numeric data. That include strings, booleans,
|
||||
* bytes and containers containing only these things (recursively).
|
||||
*
|
||||
+ * While this function can safely handle untrusted, non-normal data, it is
|
||||
+ * recommended to check whether the input is in normal form beforehand, using
|
||||
+ * g_variant_is_normal_form(), and to reject non-normal inputs if your
|
||||
+ * application can be strict about what inputs it rejects.
|
||||
+ *
|
||||
* The returned value is always in normal form and is marked as trusted.
|
||||
*
|
||||
* Returns: (transfer full): the byteswapped form of @value
|
||||
@@ -5933,21 +5974,20 @@ g_variant_byteswap (GVariant *value)
|
||||
|
||||
g_variant_type_info_query (type_info, &alignment, NULL);
|
||||
|
||||
- if (alignment)
|
||||
- /* (potentially) contains multi-byte numeric data */
|
||||
+ if (alignment && g_variant_is_normal_form (value))
|
||||
{
|
||||
+ /* (potentially) contains multi-byte numeric data, but is also already in
|
||||
+ * normal form so we can use a faster byteswapping codepath on the
|
||||
+ * serialised data */
|
||||
GVariantSerialised serialised = { 0, };
|
||||
- GVariant *trusted;
|
||||
GBytes *bytes;
|
||||
|
||||
- trusted = g_variant_get_normal_form (value);
|
||||
- serialised.type_info = g_variant_get_type_info (trusted);
|
||||
- serialised.size = g_variant_get_size (trusted);
|
||||
+ serialised.type_info = g_variant_get_type_info (value);
|
||||
+ serialised.size = g_variant_get_size (value);
|
||||
serialised.data = g_malloc (serialised.size);
|
||||
serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
|
||||
serialised.checked_offsets_up_to = G_MAXSIZE;
|
||||
- g_variant_store (trusted, serialised.data);
|
||||
- g_variant_unref (trusted);
|
||||
+ g_variant_store (value, serialised.data);
|
||||
|
||||
g_variant_serialised_byteswap (serialised);
|
||||
|
||||
@@ -5955,6 +5995,9 @@ g_variant_byteswap (GVariant *value)
|
||||
new = g_variant_ref_sink (g_variant_new_from_bytes (g_variant_get_type (value), bytes, TRUE));
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
+ else if (alignment)
|
||||
+ /* (potentially) contains multi-byte numeric data */
|
||||
+ new = g_variant_ref_sink (g_variant_deep_copy (value, TRUE));
|
||||
else
|
||||
/* contains no multi-byte data */
|
||||
new = g_variant_get_normal_form (value);
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 3dda08e..679dd40 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -2284,24 +2284,67 @@ serialise_tree (TreeInstance *tree,
|
||||
static void
|
||||
test_byteswap (void)
|
||||
{
|
||||
- GVariantSerialised one = { 0, }, two = { 0, };
|
||||
+ GVariantSerialised one = { 0, }, two = { 0, }, three = { 0, };
|
||||
TreeInstance *tree;
|
||||
-
|
||||
+ GVariant *one_variant = NULL;
|
||||
+ GVariant *two_variant = NULL;
|
||||
+ GVariant *two_byteswapped = NULL;
|
||||
+ GVariant *three_variant = NULL;
|
||||
+ GVariant *three_byteswapped = NULL;
|
||||
+ guint8 *three_data_copy = NULL;
|
||||
+ gsize three_size_copy = 0;
|
||||
+
|
||||
+ /* Write a tree out twice, once normally and once byteswapped. */
|
||||
tree = tree_instance_new (NULL, 3);
|
||||
serialise_tree (tree, &one);
|
||||
|
||||
+ one_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (one.type_info)),
|
||||
+ one.data, one.size, FALSE, NULL, NULL);
|
||||
+
|
||||
i_am_writing_byteswapped = TRUE;
|
||||
serialise_tree (tree, &two);
|
||||
+ serialise_tree (tree, &three);
|
||||
i_am_writing_byteswapped = FALSE;
|
||||
|
||||
- g_variant_serialised_byteswap (two);
|
||||
-
|
||||
- g_assert_cmpmem (one.data, one.size, two.data, two.size);
|
||||
- g_assert_cmpuint (one.depth, ==, two.depth);
|
||||
-
|
||||
+ /* Swap the first byteswapped one back using the function we want to test. */
|
||||
+ two_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (two.type_info)),
|
||||
+ two.data, two.size, FALSE, NULL, NULL);
|
||||
+ two_byteswapped = g_variant_byteswap (two_variant);
|
||||
+
|
||||
+ /* Make the second byteswapped one non-normal (hopefully), and then byteswap
|
||||
+ * it back using the function we want to test in its non-normal mode.
|
||||
+ * This might not work because it’s not necessarily possible to make an
|
||||
+ * arbitrary random variant non-normal. Adding a single zero byte to the end
|
||||
+ * often makes something non-normal but still readable. */
|
||||
+ three_size_copy = three.size + 1;
|
||||
+ three_data_copy = g_malloc (three_size_copy);
|
||||
+ memcpy (three_data_copy, three.data, three.size);
|
||||
+ three_data_copy[three.size] = '\0';
|
||||
+
|
||||
+ three_variant = g_variant_new_from_data (G_VARIANT_TYPE (g_variant_type_info_get_type_string (three.type_info)),
|
||||
+ three_data_copy, three_size_copy, FALSE, NULL, NULL);
|
||||
+ three_byteswapped = g_variant_byteswap (three_variant);
|
||||
+
|
||||
+ /* Check they’re the same. We can always compare @one_variant and
|
||||
+ * @two_byteswapped. We can only compare @two_byteswapped and
|
||||
+ * @three_byteswapped if @two_variant and @three_variant are equal: in that
|
||||
+ * case, the corruption to @three_variant was enough to make it non-normal but
|
||||
+ * not enough to change its value. */
|
||||
+ g_assert_cmpvariant (one_variant, two_byteswapped);
|
||||
+
|
||||
+ if (g_variant_equal (two_variant, three_variant))
|
||||
+ g_assert_cmpvariant (two_byteswapped, three_byteswapped);
|
||||
+
|
||||
+ g_variant_unref (three_byteswapped);
|
||||
+ g_variant_unref (three_variant);
|
||||
+ g_variant_unref (two_byteswapped);
|
||||
+ g_variant_unref (two_variant);
|
||||
+ g_variant_unref (one_variant);
|
||||
tree_instance_free (tree);
|
||||
g_free (one.data);
|
||||
g_free (two.data);
|
||||
+ g_free (three.data);
|
||||
+ g_free (three_data_copy);
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.24.4
|
||||
|
||||
49
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
Normal file
49
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32636.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
From 21a204147b16539b3eda3143b32844c49e29f4d4 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 17 Aug 2023 11:33:49 +0000
|
||||
Subject: [PATCH] gvariant: Propagate trust when getting a child of a
|
||||
serialised variant
|
||||
|
||||
If a variant is trusted, that means all its children are trusted, so
|
||||
ensure that their checked offsets are set as such.
|
||||
|
||||
This allows a lot of the offset table checks to be avoided when getting
|
||||
children from trusted serialised tuples, which speeds things up.
|
||||
|
||||
No unit test is included because this is just a performance fix. If
|
||||
there are other slownesses, or regressions, in serialised `GVariant`
|
||||
performance, the fuzzing setup will catch them like it did this one.
|
||||
|
||||
This change does reduce the time to run the oss-fuzz reproducer from 80s
|
||||
to about 0.7s on my machine.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Fixes: #2841
|
||||
oss-fuzz#54314
|
||||
|
||||
CVE: CVE-2023-32636
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/21a204147b16539b3eda3143b32844c49e29f4d4]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-core.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
|
||||
index 1b9d5cc..ed57c70 100644
|
||||
--- a/glib/gvariant-core.c
|
||||
+++ b/glib/gvariant-core.c
|
||||
@@ -1173,8 +1173,8 @@ g_variant_get_child_value (GVariant *value,
|
||||
child->contents.serialised.bytes =
|
||||
g_bytes_ref (value->contents.serialised.bytes);
|
||||
child->contents.serialised.data = s_child.data;
|
||||
- child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
|
||||
- child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
|
||||
+ child->contents.serialised.ordered_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.ordered_offsets_up_to;
|
||||
+ child->contents.serialised.checked_offsets_up_to = (value->state & STATE_TRUSTED) ? G_MAXSIZE : s_child.checked_offsets_up_to;
|
||||
|
||||
return child;
|
||||
}
|
||||
--
|
||||
2.24.4
|
||||
|
||||
154
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
Normal file
154
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32643.patch
Normal file
@@ -0,0 +1,154 @@
|
||||
From 78da5faccb3e065116b75b3ff87ff55381da6c76 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 17 Aug 2023 11:24:43 +0000
|
||||
Subject: [PATCH] gvariant: Check offset table doesn't fall outside variant
|
||||
bounds
|
||||
|
||||
When dereferencing the first entry in the offset table for a tuple,
|
||||
check that it doesn’t fall outside the bounds of the variant first.
|
||||
|
||||
This prevents an out-of-bounds read from some non-normal tuples.
|
||||
|
||||
This bug was introduced in commit 73d0aa81c2575a5c9ae77d.
|
||||
|
||||
Includes a unit test, although the test will likely only catch the
|
||||
original bug if run with asan enabled.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Fixes: #2840
|
||||
oss-fuzz#54302
|
||||
|
||||
CVE: CVE-2023-32643
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/78da5faccb3e065116b75b3ff87ff55381da6c76]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-serialiser.c | 12 ++++++--
|
||||
glib/tests/gvariant.c | 63 ++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 72 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index 5aa2cbc..4e50ed7 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -979,7 +979,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
|
||||
|
||||
member_info = g_variant_type_info_member_info (value.type_info, index_);
|
||||
|
||||
- if (member_info->i + 1)
|
||||
+ if (member_info->i + 1 &&
|
||||
+ offset_size * (member_info->i + 1) <= value.size)
|
||||
member_start = gvs_read_unaligned_le (value.data + value.size -
|
||||
offset_size * (member_info->i + 1),
|
||||
offset_size);
|
||||
@@ -990,7 +991,8 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
|
||||
member_start &= member_info->b;
|
||||
member_start |= member_info->c;
|
||||
|
||||
- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
|
||||
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST &&
|
||||
+ offset_size * (member_info->i + 1) <= value.size)
|
||||
member_end = value.size - offset_size * (member_info->i + 1);
|
||||
|
||||
else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
|
||||
@@ -1001,11 +1003,15 @@ gvs_tuple_get_member_bounds (GVariantSerialised value,
|
||||
member_end = member_start + fixed_size;
|
||||
}
|
||||
|
||||
- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
|
||||
+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET &&
|
||||
+ offset_size * (member_info->i + 2) <= value.size)
|
||||
member_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
offset_size * (member_info->i + 2),
|
||||
offset_size);
|
||||
|
||||
+ else /* invalid */
|
||||
+ member_end = G_MAXSIZE;
|
||||
+
|
||||
if (out_member_start != NULL)
|
||||
*out_member_start = member_start;
|
||||
if (out_member_end != NULL)
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 679dd40..2eca8be 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -5432,6 +5432,67 @@ test_normal_checking_tuple_offsets4 (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* This is a regression test that dereferencing the first element in the offset
|
||||
+ * table doesn’t dereference memory before the start of the GVariant. The first
|
||||
+ * element in the offset table gives the offset of the final member in the
|
||||
+ * tuple (the offset table is stored in reverse), and the position of this final
|
||||
+ * member is needed to check that none of the tuple members overlap with the
|
||||
+ * offset table
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2840 */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets5 (void)
|
||||
+{
|
||||
+ /* A tuple of type (sss) in normal form would have an offset table with two
|
||||
+ * entries:
|
||||
+ * - The first entry (lowest index in the table) gives the offset of the
|
||||
+ * third `s` in the tuple, as the offset table is reversed compared to the
|
||||
+ * tuple members.
|
||||
+ * - The second entry (highest index in the table) gives the offset of the
|
||||
+ * second `s` in the tuple.
|
||||
+ * - The offset of the first `s` in the tuple is always 0.
|
||||
+ *
|
||||
+ * See §2.5.4 (Structures) of the GVariant specification for details, noting
|
||||
+ * that the table is only layed out this way because all three members of the
|
||||
+ * tuple have non-fixed sizes.
|
||||
+ *
|
||||
+ * It’s not clear whether the 0xaa data of this variant is part of the strings
|
||||
+ * in the tuple, or part of the offset table. It doesn’t really matter. This
|
||||
+ * is a regression test to check that the code to validate the offset table
|
||||
+ * doesn’t unconditionally try to access the first entry in the offset table
|
||||
+ * by subtracting the table size from the end of the GVariant data.
|
||||
+ *
|
||||
+ * In this non-normal case, that would result in an address off the start of
|
||||
+ * the GVariant data, and an out-of-bounds read, because the GVariant is one
|
||||
+ * byte long, but the offset table is calculated as two bytes long (with 1B
|
||||
+ * sized entries) from the tuple’s type.
|
||||
+ */
|
||||
+ const GVariantType *data_type = G_VARIANT_TYPE ("(sss)");
|
||||
+ const guint8 data[] = { 0xaa };
|
||||
+ gsize size = sizeof (data);
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2840");
|
||||
+
|
||||
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (variant));
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+
|
||||
+ expected = g_variant_new_parsed ("('', '', '')");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
/* Test that an otherwise-valid serialised GVariant is considered non-normal if
|
||||
* its offset table entries are too wide.
|
||||
*
|
||||
@@ -5680,6 +5741,8 @@ main (int argc, char **argv)
|
||||
test_normal_checking_tuple_offsets3);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
|
||||
test_normal_checking_tuple_offsets4);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets5",
|
||||
+ test_normal_checking_tuple_offsets5);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets/minimal-sized",
|
||||
test_normal_checking_tuple_offsets_minimal_sized);
|
||||
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
|
||||
--
|
||||
2.24.4
|
||||
|
||||
103
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
Normal file
103
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0001.patch
Normal file
@@ -0,0 +1,103 @@
|
||||
From 1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1 Mon Sep 17 00:00:00 2001
|
||||
From: William Manley <will@stb-tester.com>
|
||||
Date: Wed, 9 Aug 2023 10:04:49 +0000
|
||||
Subject: [PATCH] gvariant-core: Consolidate construction of
|
||||
`GVariantSerialised`
|
||||
|
||||
So I only need to change it in one place.
|
||||
|
||||
This introduces no functional changes.
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/1deacdd4e8e35a5cf1417918ca4f6b0afa6409b1]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-core.c | 49 ++++++++++++++++++++++----------------------
|
||||
1 file changed, 25 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
|
||||
index 9397573..aa0e0a0 100644
|
||||
--- a/glib/gvariant-core.c
|
||||
+++ b/glib/gvariant-core.c
|
||||
@@ -349,6 +349,27 @@ g_variant_ensure_size (GVariant *value)
|
||||
}
|
||||
}
|
||||
|
||||
+/* < private >
|
||||
+ * g_variant_to_serialised:
|
||||
+ * @value: a #GVariant
|
||||
+ *
|
||||
+ * Gets a GVariantSerialised for a GVariant in state STATE_SERIALISED.
|
||||
+ */
|
||||
+inline static GVariantSerialised
|
||||
+g_variant_to_serialised (GVariant *value)
|
||||
+{
|
||||
+ g_assert (value->state & STATE_SERIALISED);
|
||||
+ {
|
||||
+ GVariantSerialised serialised = {
|
||||
+ value->type_info,
|
||||
+ (gpointer) value->contents.serialised.data,
|
||||
+ value->size,
|
||||
+ value->depth,
|
||||
+ };
|
||||
+ return serialised;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* < private >
|
||||
* g_variant_serialise:
|
||||
* @value: a #GVariant
|
||||
@@ -991,16 +1012,8 @@ g_variant_n_children (GVariant *value)
|
||||
g_variant_lock (value);
|
||||
|
||||
if (value->state & STATE_SERIALISED)
|
||||
- {
|
||||
- GVariantSerialised serialised = {
|
||||
- value->type_info,
|
||||
- (gpointer) value->contents.serialised.data,
|
||||
- value->size,
|
||||
- value->depth,
|
||||
- };
|
||||
-
|
||||
- n_children = g_variant_serialised_n_children (serialised);
|
||||
- }
|
||||
+ n_children = g_variant_serialised_n_children (
|
||||
+ g_variant_to_serialised (value));
|
||||
else
|
||||
n_children = value->contents.tree.n_children;
|
||||
|
||||
@@ -1061,12 +1074,7 @@ g_variant_get_child_value (GVariant *value,
|
||||
}
|
||||
|
||||
{
|
||||
- GVariantSerialised serialised = {
|
||||
- value->type_info,
|
||||
- (gpointer) value->contents.serialised.data,
|
||||
- value->size,
|
||||
- value->depth,
|
||||
- };
|
||||
+ GVariantSerialised serialised = g_variant_to_serialised (value);
|
||||
GVariantSerialised s_child;
|
||||
GVariant *child;
|
||||
|
||||
@@ -1179,14 +1187,7 @@ g_variant_is_normal_form (GVariant *value)
|
||||
|
||||
if (value->state & STATE_SERIALISED)
|
||||
{
|
||||
- GVariantSerialised serialised = {
|
||||
- value->type_info,
|
||||
- (gpointer) value->contents.serialised.data,
|
||||
- value->size,
|
||||
- value->depth
|
||||
- };
|
||||
-
|
||||
- if (g_variant_serialised_is_normal (serialised))
|
||||
+ if (g_variant_serialised_is_normal (g_variant_to_serialised (value)))
|
||||
value->state |= STATE_TRUSTED;
|
||||
}
|
||||
else
|
||||
--
|
||||
2.24.4
|
||||
|
||||
210
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
Normal file
210
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0002.patch
Normal file
@@ -0,0 +1,210 @@
|
||||
From 446e69f5edd72deb2196dee36bbaf8056caf6948 Mon Sep 17 00:00:00 2001
|
||||
From: William Manley <will@stb-tester.com>
|
||||
Date: Wed, 9 Aug 2023 10:39:34 +0000
|
||||
Subject: [PATCH] gvariant-serialiser: Factor out functions for dealing with
|
||||
framing offsets
|
||||
|
||||
This introduces no functional changes.
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/446e69f5edd72deb2196dee36bbaf8056caf6948]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-serialiser.c | 108 +++++++++++++++++++------------------
|
||||
1 file changed, 57 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index 83e9d85..c7c2114 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -633,30 +633,62 @@ gvs_calculate_total_size (gsize body_size,
|
||||
return body_size + 8 * offsets;
|
||||
}
|
||||
|
||||
+struct Offsets
|
||||
+{
|
||||
+ gsize data_size;
|
||||
+
|
||||
+ guchar *array;
|
||||
+ gsize length;
|
||||
+ guint offset_size;
|
||||
+
|
||||
+ gboolean is_normal;
|
||||
+};
|
||||
+
|
||||
static gsize
|
||||
-gvs_variable_sized_array_n_children (GVariantSerialised value)
|
||||
+gvs_offsets_get_offset_n (struct Offsets *offsets,
|
||||
+ gsize n)
|
||||
+{
|
||||
+ return gvs_read_unaligned_le (
|
||||
+ offsets->array + (offsets->offset_size * n), offsets->offset_size);
|
||||
+}
|
||||
+
|
||||
+static struct Offsets
|
||||
+gvs_variable_sized_array_get_frame_offsets (GVariantSerialised value)
|
||||
{
|
||||
+ struct Offsets out = { 0, };
|
||||
gsize offsets_array_size;
|
||||
- gsize offset_size;
|
||||
gsize last_end;
|
||||
|
||||
if (value.size == 0)
|
||||
- return 0;
|
||||
-
|
||||
- offset_size = gvs_get_offset_size (value.size);
|
||||
+ {
|
||||
+ out.is_normal = TRUE;
|
||||
+ return out;
|
||||
+ }
|
||||
|
||||
- last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
- offset_size, offset_size);
|
||||
+ out.offset_size = gvs_get_offset_size (value.size);
|
||||
+ last_end = gvs_read_unaligned_le (value.data + value.size - out.offset_size,
|
||||
+ out.offset_size);
|
||||
|
||||
if (last_end > value.size)
|
||||
- return 0;
|
||||
+ return out; /* offsets not normal */
|
||||
|
||||
offsets_array_size = value.size - last_end;
|
||||
|
||||
- if (offsets_array_size % offset_size)
|
||||
- return 0;
|
||||
+ if (offsets_array_size % out.offset_size)
|
||||
+ return out; /* offsets not normal */
|
||||
+
|
||||
+ out.data_size = last_end;
|
||||
+ out.array = value.data + last_end;
|
||||
+ out.length = offsets_array_size / out.offset_size;
|
||||
+ out.is_normal = TRUE;
|
||||
|
||||
- return offsets_array_size / offset_size;
|
||||
+ return out;
|
||||
+}
|
||||
+
|
||||
+static gsize
|
||||
+gvs_variable_sized_array_n_children (GVariantSerialised value)
|
||||
+{
|
||||
+ return gvs_variable_sized_array_get_frame_offsets (value).length;
|
||||
}
|
||||
|
||||
static GVariantSerialised
|
||||
@@ -664,8 +696,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
gsize index_)
|
||||
{
|
||||
GVariantSerialised child = { 0, };
|
||||
- gsize offset_size;
|
||||
- gsize last_end;
|
||||
+
|
||||
+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
|
||||
+
|
||||
gsize start;
|
||||
gsize end;
|
||||
|
||||
@@ -673,18 +706,11 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
g_variant_type_info_ref (child.type_info);
|
||||
child.depth = value.depth + 1;
|
||||
|
||||
- offset_size = gvs_get_offset_size (value.size);
|
||||
-
|
||||
- last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
- offset_size, offset_size);
|
||||
-
|
||||
if (index_ > 0)
|
||||
{
|
||||
guint alignment;
|
||||
|
||||
- start = gvs_read_unaligned_le (value.data + last_end +
|
||||
- (offset_size * (index_ - 1)),
|
||||
- offset_size);
|
||||
+ start = gvs_offsets_get_offset_n (&offsets, index_ - 1);
|
||||
|
||||
g_variant_type_info_query (child.type_info, &alignment, NULL);
|
||||
start += (-start) & alignment;
|
||||
@@ -692,11 +718,9 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
else
|
||||
start = 0;
|
||||
|
||||
- end = gvs_read_unaligned_le (value.data + last_end +
|
||||
- (offset_size * index_),
|
||||
- offset_size);
|
||||
+ end = gvs_offsets_get_offset_n (&offsets, index_);
|
||||
|
||||
- if (start < end && end <= value.size && end <= last_end)
|
||||
+ if (start < end && end <= value.size && end <= offsets.data_size)
|
||||
{
|
||||
child.data = value.data + start;
|
||||
child.size = end - start;
|
||||
@@ -768,34 +792,16 @@ static gboolean
|
||||
gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
{
|
||||
GVariantSerialised child = { 0, };
|
||||
- gsize offsets_array_size;
|
||||
- guchar *offsets_array;
|
||||
- guint offset_size;
|
||||
guint alignment;
|
||||
- gsize last_end;
|
||||
- gsize length;
|
||||
gsize offset;
|
||||
gsize i;
|
||||
|
||||
- if (value.size == 0)
|
||||
- return TRUE;
|
||||
-
|
||||
- offset_size = gvs_get_offset_size (value.size);
|
||||
- last_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
- offset_size, offset_size);
|
||||
+ struct Offsets offsets = gvs_variable_sized_array_get_frame_offsets (value);
|
||||
|
||||
- if (last_end > value.size)
|
||||
+ if (!offsets.is_normal)
|
||||
return FALSE;
|
||||
|
||||
- offsets_array_size = value.size - last_end;
|
||||
-
|
||||
- if (offsets_array_size % offset_size)
|
||||
- return FALSE;
|
||||
-
|
||||
- offsets_array = value.data + value.size - offsets_array_size;
|
||||
- length = offsets_array_size / offset_size;
|
||||
-
|
||||
- if (length == 0)
|
||||
+ if (value.size != 0 && offsets.length == 0)
|
||||
return FALSE;
|
||||
|
||||
child.type_info = g_variant_type_info_element (value.type_info);
|
||||
@@ -803,14 +809,14 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
child.depth = value.depth + 1;
|
||||
offset = 0;
|
||||
|
||||
- for (i = 0; i < length; i++)
|
||||
+ for (i = 0; i < offsets.length; i++)
|
||||
{
|
||||
gsize this_end;
|
||||
|
||||
- this_end = gvs_read_unaligned_le (offsets_array + offset_size * i,
|
||||
- offset_size);
|
||||
+ this_end = gvs_read_unaligned_le (offsets.array + offsets.offset_size * i,
|
||||
+ offsets.offset_size);
|
||||
|
||||
- if (this_end < offset || this_end > last_end)
|
||||
+ if (this_end < offset || this_end > offsets.data_size)
|
||||
return FALSE;
|
||||
|
||||
while (offset & alignment)
|
||||
@@ -832,7 +838,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
offset = this_end;
|
||||
}
|
||||
|
||||
- g_assert (offset == last_end);
|
||||
+ g_assert (offset == offsets.data_size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
--
|
||||
2.24.4
|
||||
|
||||
417
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
Normal file
417
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0003.patch
Normal file
@@ -0,0 +1,417 @@
|
||||
From ade71fb544391b2e33e1859645726bfee0d5eaaf Mon Sep 17 00:00:00 2001
|
||||
From: William Manley <will@stb-tester.com>
|
||||
Date: Wed, 16 Aug 2023 03:12:21 +0000
|
||||
Subject: [PATCH] gvariant: Don't allow child elements to overlap with each
|
||||
other
|
||||
|
||||
If different elements of a variable sized array can overlap with each
|
||||
other then we can cause a `GVariant` to normalise to a much larger type.
|
||||
|
||||
This commit changes the behaviour of `GVariant` with non-normal form data. If
|
||||
an invalid frame offset is found all subsequent elements are given their
|
||||
default value.
|
||||
|
||||
When retrieving an element at index `n` we scan the frame offsets up to index
|
||||
`n` and if they are not in order we return an element with the default value
|
||||
for that type. This guarantees that elements don't overlap with each
|
||||
other. We remember the offset we've scanned up to so we don't need to
|
||||
repeat this work on subsequent accesses. We skip these checks for trusted
|
||||
data.
|
||||
|
||||
Unfortunately this makes random access of untrusted data O(n) — at least
|
||||
on first access. It doesn't affect the algorithmic complexity of accessing
|
||||
elements in order, such as when using the `GVariantIter` interface. Also:
|
||||
the cost of validation will be amortised as the `GVariant` instance is
|
||||
continued to be used.
|
||||
|
||||
I've implemented this with 4 different functions, 1 for each element size,
|
||||
rather than looping calling `gvs_read_unaligned_le` in the hope that the
|
||||
compiler will find it easy to optimise and should produce fairly tight
|
||||
code.
|
||||
|
||||
Fixes: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/ade71fb544391b2e33e1859645726bfee0d5eaaf]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-core.c | 35 ++++++++++++++++
|
||||
glib/gvariant-serialiser.c | 86 ++++++++++++++++++++++++++++++++++++--
|
||||
glib/gvariant-serialiser.h | 8 ++++
|
||||
glib/tests/gvariant.c | 45 ++++++++++++++++++++
|
||||
4 files changed, 171 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
|
||||
index aa0e0a0..9b51e15 100644
|
||||
--- a/glib/gvariant-core.c
|
||||
+++ b/glib/gvariant-core.c
|
||||
@@ -65,6 +65,7 @@ struct _GVariant
|
||||
{
|
||||
GBytes *bytes;
|
||||
gconstpointer data;
|
||||
+ gsize ordered_offsets_up_to;
|
||||
} serialised;
|
||||
|
||||
struct
|
||||
@@ -162,6 +163,24 @@ struct _GVariant
|
||||
* if .data pointed to the appropriate number of nul
|
||||
* bytes.
|
||||
*
|
||||
+ * .ordered_offsets_up_to: If ordered_offsets_up_to == n this means that all
|
||||
+ * the frame offsets up to and including the frame
|
||||
+ * offset determining the end of element n are in
|
||||
+ * order. This guarantees that the bytes of element
|
||||
+ * n don't overlap with any previous element.
|
||||
+ *
|
||||
+ * For trusted data this is set to G_MAXSIZE and we
|
||||
+ * don't check that the frame offsets are in order.
|
||||
+ *
|
||||
+ * Note: This doesn't imply the offsets are good in
|
||||
+ * any way apart from their ordering. In particular
|
||||
+ * offsets may be out of bounds for this value or
|
||||
+ * may imply that the data overlaps the frame
|
||||
+ * offsets themselves.
|
||||
+ *
|
||||
+ * This field is only relevant for arrays of non
|
||||
+ * fixed width types.
|
||||
+ *
|
||||
* .tree: Only valid when the instance is in tree form.
|
||||
*
|
||||
* Note that accesses from other threads could result in
|
||||
@@ -365,6 +384,7 @@ g_variant_to_serialised (GVariant *value)
|
||||
(gpointer) value->contents.serialised.data,
|
||||
value->size,
|
||||
value->depth,
|
||||
+ value->contents.serialised.ordered_offsets_up_to,
|
||||
};
|
||||
return serialised;
|
||||
}
|
||||
@@ -396,6 +416,7 @@ g_variant_serialise (GVariant *value,
|
||||
serialised.size = value->size;
|
||||
serialised.data = data;
|
||||
serialised.depth = value->depth;
|
||||
+ serialised.ordered_offsets_up_to = 0;
|
||||
|
||||
children = (gpointer *) value->contents.tree.children;
|
||||
n_children = value->contents.tree.n_children;
|
||||
@@ -439,6 +460,15 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
|
||||
g_assert (serialised->size == value->size);
|
||||
serialised->depth = value->depth;
|
||||
|
||||
+ if (value->state & STATE_SERIALISED)
|
||||
+ {
|
||||
+ serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ serialised->ordered_offsets_up_to = 0;
|
||||
+ }
|
||||
+
|
||||
if (serialised->data)
|
||||
/* g_variant_store() is a public API, so it
|
||||
* it will reacquire the lock if it needs to.
|
||||
@@ -481,6 +511,7 @@ g_variant_ensure_serialised (GVariant *value)
|
||||
bytes = g_bytes_new_take (data, value->size);
|
||||
value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
|
||||
value->contents.serialised.bytes = bytes;
|
||||
+ value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
|
||||
value->state |= STATE_SERIALISED;
|
||||
}
|
||||
}
|
||||
@@ -561,6 +592,7 @@ g_variant_new_from_bytes (const GVariantType *type,
|
||||
serialised.type_info = value->type_info;
|
||||
serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
|
||||
serialised.depth = 0;
|
||||
+ serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
|
||||
if (!g_variant_serialised_check (serialised))
|
||||
{
|
||||
@@ -610,6 +642,8 @@ g_variant_new_from_bytes (const GVariantType *type,
|
||||
value->contents.serialised.data = g_bytes_get_data (bytes, &value->size);
|
||||
}
|
||||
|
||||
+ value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
+
|
||||
g_clear_pointer (&owned_bytes, g_bytes_unref);
|
||||
|
||||
return value;
|
||||
@@ -1108,6 +1142,7 @@ g_variant_get_child_value (GVariant *value,
|
||||
child->contents.serialised.bytes =
|
||||
g_bytes_ref (value->contents.serialised.bytes);
|
||||
child->contents.serialised.data = s_child.data;
|
||||
+ child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
|
||||
|
||||
return child;
|
||||
}
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index c7c2114..fe0b1a4 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright © 2007, 2008 Ryan Lortie
|
||||
* Copyright © 2010 Codethink Limited
|
||||
+ * Copyright © 2020 William Manley
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -264,6 +265,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
|
||||
value.type_info = g_variant_type_info_element (value.type_info);
|
||||
g_variant_type_info_ref (value.type_info);
|
||||
value.depth++;
|
||||
+ value.ordered_offsets_up_to = 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -295,7 +297,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
|
||||
{
|
||||
if (n_children)
|
||||
{
|
||||
- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1 };
|
||||
+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
|
||||
|
||||
gvs_filler (&child, children[0]);
|
||||
}
|
||||
@@ -317,6 +319,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
|
||||
/* proper element size: "Just". recurse to the child. */
|
||||
value.type_info = g_variant_type_info_element (value.type_info);
|
||||
value.depth++;
|
||||
+ value.ordered_offsets_up_to = 0;
|
||||
|
||||
return g_variant_serialised_is_normal (value);
|
||||
}
|
||||
@@ -358,6 +361,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
|
||||
value.data = NULL;
|
||||
|
||||
value.depth++;
|
||||
+ value.ordered_offsets_up_to = 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -388,7 +392,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
|
||||
{
|
||||
if (n_children)
|
||||
{
|
||||
- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1 };
|
||||
+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
|
||||
|
||||
/* write the data for the child. */
|
||||
gvs_filler (&child, children[0]);
|
||||
@@ -408,6 +412,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
|
||||
value.type_info = g_variant_type_info_element (value.type_info);
|
||||
value.size--;
|
||||
value.depth++;
|
||||
+ value.ordered_offsets_up_to = 0;
|
||||
|
||||
return g_variant_serialised_is_normal (value);
|
||||
}
|
||||
@@ -691,6 +696,32 @@ gvs_variable_sized_array_n_children (GVariantSerialised value)
|
||||
return gvs_variable_sized_array_get_frame_offsets (value).length;
|
||||
}
|
||||
|
||||
+/* Find the index of the first out-of-order element in @data, assuming that
|
||||
+ * @data is an array of elements of given @type, starting at index @start and
|
||||
+ * containing a further @len-@start elements. */
|
||||
+#define DEFINE_FIND_UNORDERED(type) \
|
||||
+ static gsize \
|
||||
+ find_unordered_##type (const guint8 *data, gsize start, gsize len) \
|
||||
+ { \
|
||||
+ gsize off; \
|
||||
+ type current, previous; \
|
||||
+ \
|
||||
+ memcpy (&previous, data + start * sizeof (current), sizeof (current)); \
|
||||
+ for (off = (start + 1) * sizeof (current); off < len * sizeof (current); off += sizeof (current)) \
|
||||
+ { \
|
||||
+ memcpy (¤t, data + off, sizeof (current)); \
|
||||
+ if (current < previous) \
|
||||
+ break; \
|
||||
+ previous = current; \
|
||||
+ } \
|
||||
+ return off / sizeof (current) - 1; \
|
||||
+ }
|
||||
+
|
||||
+DEFINE_FIND_UNORDERED (guint8);
|
||||
+DEFINE_FIND_UNORDERED (guint16);
|
||||
+DEFINE_FIND_UNORDERED (guint32);
|
||||
+DEFINE_FIND_UNORDERED (guint64);
|
||||
+
|
||||
static GVariantSerialised
|
||||
gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
gsize index_)
|
||||
@@ -706,6 +737,49 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
g_variant_type_info_ref (child.type_info);
|
||||
child.depth = value.depth + 1;
|
||||
|
||||
+ /* If the requested @index_ is beyond the set of indices whose framing offsets
|
||||
+ * have been checked, check the remaining offsets to see whether they’re
|
||||
+ * normal (in order, no overlapping array elements). */
|
||||
+ if (index_ > value.ordered_offsets_up_to)
|
||||
+ {
|
||||
+ switch (offsets.offset_size)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ {
|
||||
+ value.ordered_offsets_up_to = find_unordered_guint8 (
|
||||
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+ case 2:
|
||||
+ {
|
||||
+ value.ordered_offsets_up_to = find_unordered_guint16 (
|
||||
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+ case 4:
|
||||
+ {
|
||||
+ value.ordered_offsets_up_to = find_unordered_guint32 (
|
||||
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+ case 8:
|
||||
+ {
|
||||
+ value.ordered_offsets_up_to = find_unordered_guint64 (
|
||||
+ offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ /* gvs_get_offset_size() only returns maximum 8 */
|
||||
+ g_assert_not_reached ();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (index_ > value.ordered_offsets_up_to)
|
||||
+ {
|
||||
+ /* Offsets are invalid somewhere, so return an empty child. */
|
||||
+ return child;
|
||||
+ }
|
||||
+
|
||||
if (index_ > 0)
|
||||
{
|
||||
guint alignment;
|
||||
@@ -840,6 +914,9 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
|
||||
g_assert (offset == offsets.data_size);
|
||||
|
||||
+ /* All offsets have now been checked. */
|
||||
+ value.ordered_offsets_up_to = G_MAXSIZE;
|
||||
+
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1072,7 +1149,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
const GVariantMemberInfo *member_info;
|
||||
- GVariantSerialised child;
|
||||
+ GVariantSerialised child = { 0, };
|
||||
gsize fixed_size;
|
||||
guint alignment;
|
||||
gsize end;
|
||||
@@ -1132,6 +1209,9 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
offset = end;
|
||||
}
|
||||
|
||||
+ /* All element bounds have been checked above. */
|
||||
+ value.ordered_offsets_up_to = G_MAXSIZE;
|
||||
+
|
||||
{
|
||||
gsize fixed_size;
|
||||
guint alignment;
|
||||
diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
|
||||
index 81343e9..99d18ef 100644
|
||||
--- a/glib/gvariant-serialiser.h
|
||||
+++ b/glib/gvariant-serialiser.h
|
||||
@@ -29,6 +29,14 @@ typedef struct
|
||||
guchar *data;
|
||||
gsize size;
|
||||
gsize depth; /* same semantics as GVariant.depth */
|
||||
+ /* If ordered_offsets_up_to == n this means that all the frame offsets up to and
|
||||
+ * including the frame offset determining the end of element n are in order.
|
||||
+ * This guarantees that the bytes of element n don't overlap with any previous
|
||||
+ * element.
|
||||
+ *
|
||||
+ * This is both read and set by g_variant_serialised_get_child for arrays of
|
||||
+ * non-fixed-width types */
|
||||
+ gsize ordered_offsets_up_to;
|
||||
} GVariantSerialised;
|
||||
|
||||
/* deserialisation */
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 0e5ec8e..967e9a1 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2010 Codethink Limited
|
||||
+ * Copyright © 2020 William Manley
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -1283,6 +1284,7 @@ random_instance_filler (GVariantSerialised *serialised,
|
||||
serialised->size = instance->size;
|
||||
|
||||
serialised->depth = 0;
|
||||
+ serialised->ordered_offsets_up_to = 0;
|
||||
|
||||
g_assert_true (serialised->type_info == instance->type_info);
|
||||
g_assert_cmpuint (serialised->size, ==, instance->size);
|
||||
@@ -5039,6 +5041,47 @@ test_normal_checking_array_offsets (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* This is a regression test that we can't have non-normal values that take up
|
||||
+ * significantly more space than the normal equivalent, by specifying the
|
||||
+ * offset table entries so that array elements overlap.
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_832242 */
|
||||
+static void
|
||||
+test_normal_checking_array_offsets2 (void)
|
||||
+{
|
||||
+ const guint8 data[] = {
|
||||
+ 'h', 'i', '\0',
|
||||
+ 0x03, 0x00, 0x03,
|
||||
+ 0x06, 0x00, 0x06,
|
||||
+ 0x09, 0x00, 0x09,
|
||||
+ 0x0c, 0x00, 0x0c,
|
||||
+ 0x0f, 0x00, 0x0f,
|
||||
+ 0x12, 0x00, 0x12,
|
||||
+ 0x15, 0x00, 0x15,
|
||||
+ };
|
||||
+ gsize size = sizeof (data);
|
||||
+ const GVariantType *aaaaaaas = G_VARIANT_TYPE ("aaaaaaas");
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ variant = g_variant_new_from_data (aaaaaaas, data, size, FALSE, NULL, NULL);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 2);
|
||||
+
|
||||
+ expected = g_variant_new_parsed (
|
||||
+ "[[[[[[['hi', '', ''], [], []], [], []], [], []], [], []], [], []], [], []]");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
/* Test that a tuple with invalidly large values in its offset table is
|
||||
* normalised successfully without looping infinitely. */
|
||||
static void
|
||||
@@ -5206,6 +5249,8 @@ main (int argc, char **argv)
|
||||
test_normal_checking_tuples);
|
||||
g_test_add_func ("/gvariant/normal-checking/array-offsets",
|
||||
test_normal_checking_array_offsets);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/array-offsets2",
|
||||
+ test_normal_checking_array_offsets2);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
|
||||
test_normal_checking_tuple_offsets);
|
||||
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
|
||||
--
|
||||
2.24.4
|
||||
|
||||
113
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
Normal file
113
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0004.patch
Normal file
@@ -0,0 +1,113 @@
|
||||
From 345cae9c1aa7bf6752039225ef4c8d8d69fa8d76 Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Fri, 11 Aug 2023 04:09:12 +0000
|
||||
Subject: [PATCH] gvariant-serialiser: Factor out code to get bounds of a tuple
|
||||
member
|
||||
|
||||
This introduces no functional changes.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/345cae9c1aa7bf6752039225ef4c8d8d69fa8d76]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-serialiser.c | 73 ++++++++++++++++++++++++--------------
|
||||
1 file changed, 46 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index fe0b1a4..6f9b366 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -942,6 +942,51 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
* for the tuple. See the notes in gvarianttypeinfo.h.
|
||||
*/
|
||||
|
||||
+static void
|
||||
+gvs_tuple_get_member_bounds (GVariantSerialised value,
|
||||
+ gsize index_,
|
||||
+ gsize offset_size,
|
||||
+ gsize *out_member_start,
|
||||
+ gsize *out_member_end)
|
||||
+{
|
||||
+ const GVariantMemberInfo *member_info;
|
||||
+ gsize member_start, member_end;
|
||||
+
|
||||
+ member_info = g_variant_type_info_member_info (value.type_info, index_);
|
||||
+
|
||||
+ if (member_info->i + 1)
|
||||
+ member_start = gvs_read_unaligned_le (value.data + value.size -
|
||||
+ offset_size * (member_info->i + 1),
|
||||
+ offset_size);
|
||||
+ else
|
||||
+ member_start = 0;
|
||||
+
|
||||
+ member_start += member_info->a;
|
||||
+ member_start &= member_info->b;
|
||||
+ member_start |= member_info->c;
|
||||
+
|
||||
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
|
||||
+ member_end = value.size - offset_size * (member_info->i + 1);
|
||||
+
|
||||
+ else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
|
||||
+ {
|
||||
+ gsize fixed_size;
|
||||
+
|
||||
+ g_variant_type_info_query (member_info->type_info, NULL, &fixed_size);
|
||||
+ member_end = member_start + fixed_size;
|
||||
+ }
|
||||
+
|
||||
+ else /* G_VARIANT_MEMBER_ENDING_OFFSET */
|
||||
+ member_end = gvs_read_unaligned_le (value.data + value.size -
|
||||
+ offset_size * (member_info->i + 2),
|
||||
+ offset_size);
|
||||
+
|
||||
+ if (out_member_start != NULL)
|
||||
+ *out_member_start = member_start;
|
||||
+ if (out_member_end != NULL)
|
||||
+ *out_member_end = member_end;
|
||||
+}
|
||||
+
|
||||
static gsize
|
||||
gvs_tuple_n_children (GVariantSerialised value)
|
||||
{
|
||||
@@ -997,33 +1042,7 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
}
|
||||
}
|
||||
|
||||
- if (member_info->i + 1)
|
||||
- start = gvs_read_unaligned_le (value.data + value.size -
|
||||
- offset_size * (member_info->i + 1),
|
||||
- offset_size);
|
||||
- else
|
||||
- start = 0;
|
||||
-
|
||||
- start += member_info->a;
|
||||
- start &= member_info->b;
|
||||
- start |= member_info->c;
|
||||
-
|
||||
- if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_LAST)
|
||||
- end = value.size - offset_size * (member_info->i + 1);
|
||||
-
|
||||
- else if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
|
||||
- {
|
||||
- gsize fixed_size;
|
||||
-
|
||||
- g_variant_type_info_query (child.type_info, NULL, &fixed_size);
|
||||
- end = start + fixed_size;
|
||||
- child.size = fixed_size;
|
||||
- }
|
||||
-
|
||||
- else /* G_VARIANT_MEMBER_ENDING_OFFSET */
|
||||
- end = gvs_read_unaligned_le (value.data + value.size -
|
||||
- offset_size * (member_info->i + 2),
|
||||
- offset_size);
|
||||
+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
|
||||
|
||||
/* The child should not extend into the offset table. */
|
||||
if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
From 73d0aa81c2575a5c9ae77dcb94da919579014fc0 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Fri, 11 Aug 2023 04:13:02 +0000
|
||||
Subject: [PATCH] gvariant-serialiser: Rework child size calculation
|
||||
|
||||
This reduces a few duplicate calls to `g_variant_type_info_query()` and
|
||||
explains why they’re needed.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/73d0aa81c2575a5c9ae77dcb94da919579014fc0]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-serialiser.c | 31 +++++++++----------------------
|
||||
1 file changed, 9 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index 6f9b366..fb75923 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -1007,14 +1007,18 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
child.depth = value.depth + 1;
|
||||
offset_size = gvs_get_offset_size (value.size);
|
||||
|
||||
+ /* Ensure the size is set for fixed-sized children, or
|
||||
+ * g_variant_serialised_check() will fail, even if we return
|
||||
+ * (child.data == NULL) to indicate an error. */
|
||||
+ if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_FIXED)
|
||||
+ g_variant_type_info_query (child.type_info, NULL, &child.size);
|
||||
+
|
||||
/* tuples are the only (potentially) fixed-sized containers, so the
|
||||
* only ones that have to deal with the possibility of having %NULL
|
||||
* data with a non-zero %size if errors occurred elsewhere.
|
||||
*/
|
||||
if G_UNLIKELY (value.data == NULL && value.size != 0)
|
||||
{
|
||||
- g_variant_type_info_query (child.type_info, NULL, &child.size);
|
||||
-
|
||||
/* this can only happen in fixed-sized tuples,
|
||||
* so the child must also be fixed sized.
|
||||
*/
|
||||
@@ -1032,29 +1036,12 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
else
|
||||
{
|
||||
if (offset_size * (member_info->i + 1) > value.size)
|
||||
- {
|
||||
- /* if the child is fixed size, return its size.
|
||||
- * if child is not fixed-sized, return size = 0.
|
||||
- */
|
||||
- g_variant_type_info_query (child.type_info, NULL, &child.size);
|
||||
-
|
||||
- return child;
|
||||
- }
|
||||
+ return child;
|
||||
}
|
||||
|
||||
- gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
|
||||
-
|
||||
/* The child should not extend into the offset table. */
|
||||
- if (index_ != g_variant_type_info_n_members (value.type_info) - 1)
|
||||
- {
|
||||
- GVariantSerialised last_child;
|
||||
- last_child = gvs_tuple_get_child (value,
|
||||
- g_variant_type_info_n_members (value.type_info) - 1);
|
||||
- last_end = last_child.data + last_child.size - value.data;
|
||||
- g_variant_type_info_unref (last_child.type_info);
|
||||
- }
|
||||
- else
|
||||
- last_end = end;
|
||||
+ gvs_tuple_get_member_bounds (value, index_, offset_size, &start, &end);
|
||||
+ gvs_tuple_get_member_bounds (value, g_variant_type_info_n_members (value.type_info) - 1, offset_size, NULL, &last_end);
|
||||
|
||||
if (start < end && end <= value.size && end <= last_end)
|
||||
{
|
||||
--
|
||||
2.24.4
|
||||
|
||||
396
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
Normal file
396
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0006.patch
Normal file
@@ -0,0 +1,396 @@
|
||||
From 7cf6f5b69146d20948d42f0c476688fe17fef787 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Wed, 16 Aug 2023 12:09:06 +0000
|
||||
Subject: [PATCH] gvariant: Don't allow child elements of a tuple to overlap
|
||||
each other
|
||||
|
||||
This is similar to the earlier commit which prevents child elements of a
|
||||
variable-sized array from overlapping each other, but this time for
|
||||
tuples. It is based heavily on ideas by William Manley.
|
||||
|
||||
Tuples are slightly different from variable-sized arrays in that they
|
||||
contain a mixture of fixed and variable sized elements. All but one of
|
||||
the variable sized elements have an entry in the frame offsets table.
|
||||
This means that if we were to just check the ordering of the frame
|
||||
offsets table, the variable sized elements could still overlap
|
||||
interleaving fixed sized elements, which would be bad.
|
||||
|
||||
Therefore we have to check the elements rather than the frame offsets.
|
||||
|
||||
The logic of checking the elements up to the index currently being
|
||||
requested, and caching the result in `ordered_offsets_up_to`, means that
|
||||
the algorithmic cost implications are the same for this commit as for
|
||||
variable-sized arrays: an O(N) cost for these checks is amortised out
|
||||
over N accesses to O(1) per access.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Fixes: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/7cf6f5b69146d20948d42f0c476688fe17fef787]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-core.c | 6 +-
|
||||
glib/gvariant-serialiser.c | 40 ++++++++
|
||||
glib/gvariant-serialiser.h | 7 +-
|
||||
glib/gvariant.c | 1 +
|
||||
glib/tests/gvariant.c | 181 +++++++++++++++++++++++++++++++++++++
|
||||
5 files changed, 232 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
|
||||
index 9b51e15..b951cd9 100644
|
||||
--- a/glib/gvariant-core.c
|
||||
+++ b/glib/gvariant-core.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright © 2007, 2008 Ryan Lortie
|
||||
* Copyright © 2010 Codethink Limited
|
||||
+ * Copyright © 2022 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -179,7 +180,7 @@ struct _GVariant
|
||||
* offsets themselves.
|
||||
*
|
||||
* This field is only relevant for arrays of non
|
||||
- * fixed width types.
|
||||
+ * fixed width types and for tuples.
|
||||
*
|
||||
* .tree: Only valid when the instance is in tree form.
|
||||
*
|
||||
@@ -1117,6 +1118,9 @@ g_variant_get_child_value (GVariant *value,
|
||||
*/
|
||||
s_child = g_variant_serialised_get_child (serialised, index_);
|
||||
|
||||
+ /* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
|
||||
+ value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
|
||||
+
|
||||
/* Check whether this would cause nesting too deep. If so, return a fake
|
||||
* child. The only situation we expect this to happen in is with a variant,
|
||||
* as all other deeply-nested types have a static type, and hence should
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index fb75923..cd4a3e6 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -942,6 +942,10 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
* for the tuple. See the notes in gvarianttypeinfo.h.
|
||||
*/
|
||||
|
||||
+/* Note: This doesn’t guarantee that @out_member_end >= @out_member_start; that
|
||||
+ * condition may not hold true for invalid serialised variants. The caller is
|
||||
+ * responsible for checking the returned values and handling invalid ones
|
||||
+ * appropriately. */
|
||||
static void
|
||||
gvs_tuple_get_member_bounds (GVariantSerialised value,
|
||||
gsize index_,
|
||||
@@ -1028,6 +1032,42 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
return child;
|
||||
}
|
||||
|
||||
+ /* If the requested @index_ is beyond the set of indices whose framing offsets
|
||||
+ * have been checked, check the remaining offsets to see whether they’re
|
||||
+ * normal (in order, no overlapping tuple elements).
|
||||
+ *
|
||||
+ * Unlike the checks in gvs_variable_sized_array_get_child(), we have to check
|
||||
+ * all the tuple *elements* here, not just all the framing offsets, since
|
||||
+ * tuples contain a mix of elements which use framing offsets and ones which
|
||||
+ * don’t. None of them are allowed to overlap. */
|
||||
+ if (index_ > value.ordered_offsets_up_to)
|
||||
+ {
|
||||
+ gsize i, prev_i_end = 0;
|
||||
+
|
||||
+ if (value.ordered_offsets_up_to > 0)
|
||||
+ gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
|
||||
+
|
||||
+ for (i = value.ordered_offsets_up_to; i <= index_; i++)
|
||||
+ {
|
||||
+ gsize i_start, i_end;
|
||||
+
|
||||
+ gvs_tuple_get_member_bounds (value, i, offset_size, &i_start, &i_end);
|
||||
+
|
||||
+ if (i_start > i_end || i_start < prev_i_end || i_end > value.size)
|
||||
+ break;
|
||||
+
|
||||
+ prev_i_end = i_end;
|
||||
+ }
|
||||
+
|
||||
+ value.ordered_offsets_up_to = i - 1;
|
||||
+ }
|
||||
+
|
||||
+ if (index_ > value.ordered_offsets_up_to)
|
||||
+ {
|
||||
+ /* Offsets are invalid somewhere, so return an empty child. */
|
||||
+ return child;
|
||||
+ }
|
||||
+
|
||||
if (member_info->ending_type == G_VARIANT_MEMBER_ENDING_OFFSET)
|
||||
{
|
||||
if (offset_size * (member_info->i + 2) > value.size)
|
||||
diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
|
||||
index 99d18ef..144aec8 100644
|
||||
--- a/glib/gvariant-serialiser.h
|
||||
+++ b/glib/gvariant-serialiser.h
|
||||
@@ -34,8 +34,11 @@ typedef struct
|
||||
* This guarantees that the bytes of element n don't overlap with any previous
|
||||
* element.
|
||||
*
|
||||
- * This is both read and set by g_variant_serialised_get_child for arrays of
|
||||
- * non-fixed-width types */
|
||||
+ * This is both read and set by g_variant_serialised_get_child() for arrays of
|
||||
+ * non-fixed-width types, and for tuples.
|
||||
+ *
|
||||
+ * Even when dealing with tuples, @ordered_offsets_up_to is an element index,
|
||||
+ * rather than an index into the frame offsets. */
|
||||
gsize ordered_offsets_up_to;
|
||||
} GVariantSerialised;
|
||||
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index d6f68a9..cdb428e 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
|
||||
serialised.type_info = g_variant_get_type_info (trusted);
|
||||
serialised.size = g_variant_get_size (trusted);
|
||||
serialised.data = g_malloc (serialised.size);
|
||||
+ serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
|
||||
g_variant_store (trusted, serialised.data);
|
||||
g_variant_unref (trusted);
|
||||
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 967e9a1..a84b02e 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright © 2010 Codethink Limited
|
||||
* Copyright © 2020 William Manley
|
||||
+ * Copyright © 2022 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -1451,6 +1452,7 @@ test_maybe (void)
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
+ serialised.ordered_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised,
|
||||
random_instance_filler,
|
||||
@@ -1574,6 +1576,7 @@ test_array (void)
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
+ serialised.ordered_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) instances, n_children);
|
||||
@@ -1738,6 +1741,7 @@ test_tuple (void)
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
+ serialised.ordered_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) instances, n_children);
|
||||
@@ -1834,6 +1838,7 @@ test_variant (void)
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
+ serialised.ordered_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) &instance, 1);
|
||||
@@ -5106,6 +5111,176 @@ test_normal_checking_tuple_offsets (void)
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
+/* This is a regression test that we can't have non-normal values that take up
|
||||
+ * significantly more space than the normal equivalent, by specifying the
|
||||
+ * offset table entries so that tuple elements overlap.
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838503 and
|
||||
+ * https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_838513 */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets2 (void)
|
||||
+{
|
||||
+ const GVariantType *data_type = G_VARIANT_TYPE ("(yyaiyyaiyy)");
|
||||
+ const guint8 data[] = {
|
||||
+ 0x12, 0x34, 0x56, 0x78, 0x01,
|
||||
+ /*
|
||||
+ ^───────────────────┘
|
||||
+
|
||||
+ ^^^^^^^^^^ 1st yy
|
||||
+ ^^^^^^^^^^ 2nd yy
|
||||
+ ^^^^^^^^^^ 3rd yy
|
||||
+ ^^^^ Framing offsets
|
||||
+ */
|
||||
+
|
||||
+ /* If this variant was encoded normally, it would be something like this:
|
||||
+ * 0x12, 0x34, pad, pad, [array bytes], 0x56, 0x78, pad, pad, [array bytes], 0x9A, 0xBC, 0xXX
|
||||
+ * ^─────────────────────────────────────────────────────┘
|
||||
+ *
|
||||
+ * ^^^^^^^^^^ 1st yy
|
||||
+ * ^^^^^^^^^^ 2nd yy
|
||||
+ * ^^^^^^^^^^ 3rd yy
|
||||
+ * ^^^^ Framing offsets
|
||||
+ */
|
||||
+ };
|
||||
+ gsize size = sizeof (data);
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
|
||||
+
|
||||
+ expected = g_variant_new_parsed (
|
||||
+ "@(yyaiyyaiyy) (0x12, 0x34, [], 0x00, 0x00, [], 0x00, 0x00)");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
+/* This is a regression test that overlapping entries in the offset table are
|
||||
+ * decoded consistently, even though they’re non-normal.
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets3 (void)
|
||||
+{
|
||||
+ /* The expected decoding of this non-normal byte stream is complex. See
|
||||
+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
|
||||
+ * specification.
|
||||
+ *
|
||||
+ * The rule “Child Values Overlapping Framing Offsets” from the specification
|
||||
+ * says that the first `ay` must be decoded as `[0x01]` even though it
|
||||
+ * overlaps the first byte of the offset table. However, since commit
|
||||
+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
|
||||
+ * this as it’s exploitable. So the first `ay` must be given a default value.
|
||||
+ *
|
||||
+ * The second and third `ay`s must be given default values because of rule
|
||||
+ * “End Boundary Precedes Start Boundary”.
|
||||
+ *
|
||||
+ * The `i` must be given a default value because of rule “Start or End
|
||||
+ * Boundary of a Child Falls Outside the Container”.
|
||||
+ */
|
||||
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayiay)");
|
||||
+ const guint8 data[] = {
|
||||
+ 0x01, 0x00, 0x02,
|
||||
+ /*
|
||||
+ ^──┘
|
||||
+
|
||||
+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
|
||||
+ 2nd ay, bytes 2-0
|
||||
+ i, bytes 0-4
|
||||
+ 3rd ay, bytes 4-1
|
||||
+ ^^^^^^^^^^ Framing offsets
|
||||
+ */
|
||||
+ };
|
||||
+ gsize size = sizeof (data);
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (variant));
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
|
||||
+
|
||||
+ expected = g_variant_new_parsed ("@(ayayiay) ([], [], 0, [])");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
+/* This is a regression test that overlapping entries in the offset table are
|
||||
+ * decoded consistently, even though they’re non-normal.
|
||||
+ *
|
||||
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2121#note_910935 */
|
||||
+static void
|
||||
+test_normal_checking_tuple_offsets4 (void)
|
||||
+{
|
||||
+ /* The expected decoding of this non-normal byte stream is complex. See
|
||||
+ * section 2.7.3 (Handling Non-Normal Serialised Data) of the GVariant
|
||||
+ * specification.
|
||||
+ *
|
||||
+ * The rule “Child Values Overlapping Framing Offsets” from the specification
|
||||
+ * says that the first `ay` must be decoded as `[0x01]` even though it
|
||||
+ * overlaps the first byte of the offset table. However, since commit
|
||||
+ * 7eedcd76f7d5b8c98fa60013e1fe6e960bf19df3, GLib explicitly doesn’t allow
|
||||
+ * this as it’s exploitable. So the first `ay` must be given a default value.
|
||||
+ *
|
||||
+ * The second `ay` must be given a default value because of rule “End Boundary
|
||||
+ * Precedes Start Boundary”.
|
||||
+ *
|
||||
+ * The third `ay` must be given a default value because its framing offsets
|
||||
+ * overlap that of the first `ay`.
|
||||
+ */
|
||||
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ayayay)");
|
||||
+ const guint8 data[] = {
|
||||
+ 0x01, 0x00, 0x02,
|
||||
+ /*
|
||||
+ ^──┘
|
||||
+
|
||||
+ ^^^^^^^^^^ 1st ay, bytes 0-2 (but given a default value anyway, see above)
|
||||
+ 2nd ay, bytes 2-0
|
||||
+ 3rd ay, bytes 0-1
|
||||
+ ^^^^^^^^^^ Framing offsets
|
||||
+ */
|
||||
+ };
|
||||
+ gsize size = sizeof (data);
|
||||
+ GVariant *variant = NULL;
|
||||
+ GVariant *normal_variant = NULL;
|
||||
+ GVariant *expected = NULL;
|
||||
+
|
||||
+ variant = g_variant_new_from_data (data_type, data, size, FALSE, NULL, NULL);
|
||||
+ g_assert_nonnull (variant);
|
||||
+
|
||||
+ g_assert_false (g_variant_is_normal_form (variant));
|
||||
+
|
||||
+ normal_variant = g_variant_get_normal_form (variant);
|
||||
+ g_assert_nonnull (normal_variant);
|
||||
+ g_assert_cmpuint (g_variant_get_size (normal_variant), <=, size * 3);
|
||||
+
|
||||
+ expected = g_variant_new_parsed ("@(ayayay) ([], [], [])");
|
||||
+ g_assert_cmpvariant (expected, variant);
|
||||
+ g_assert_cmpvariant (expected, normal_variant);
|
||||
+
|
||||
+ g_variant_unref (expected);
|
||||
+ g_variant_unref (normal_variant);
|
||||
+ g_variant_unref (variant);
|
||||
+}
|
||||
+
|
||||
/* Test that an empty object path is normalised successfully to the base object
|
||||
* path, ‘/’. */
|
||||
static void
|
||||
@@ -5253,6 +5428,12 @@ main (int argc, char **argv)
|
||||
test_normal_checking_array_offsets2);
|
||||
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
|
||||
test_normal_checking_tuple_offsets);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets2",
|
||||
+ test_normal_checking_tuple_offsets2);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets3",
|
||||
+ test_normal_checking_tuple_offsets3);
|
||||
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets4",
|
||||
+ test_normal_checking_tuple_offsets4);
|
||||
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
|
||||
test_normal_checking_empty_object_path);
|
||||
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
From e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Wed, 16 Aug 2023 03:42:47 +0000
|
||||
Subject: [PATCH] gvariant: Port g_variant_deep_copy() to count its iterations
|
||||
directly
|
||||
|
||||
This is equivalent to what `GVariantIter` does, but it means that
|
||||
`g_variant_deep_copy()` is making its own `g_variant_get_child_value()`
|
||||
calls.
|
||||
|
||||
This will be useful in an upcoming commit, where those child values will
|
||||
be inspected a little more deeply.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/e6490c84e84ba9f182fbd83b51ff4f9f5a0a1793]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index cdb428e..fdd36be 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5799,14 +5799,13 @@ g_variant_deep_copy (GVariant *value)
|
||||
case G_VARIANT_CLASS_VARIANT:
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
- GVariantIter iter;
|
||||
- GVariant *child;
|
||||
+ gsize i, n_children;
|
||||
|
||||
g_variant_builder_init (&builder, g_variant_get_type (value));
|
||||
- g_variant_iter_init (&iter, value);
|
||||
|
||||
- while ((child = g_variant_iter_next_value (&iter)))
|
||||
+ for (i = 0, n_children = g_variant_n_children (value); i < n_children; i++)
|
||||
{
|
||||
+ GVariant *child = g_variant_get_child_value (value, i);
|
||||
g_variant_builder_add_value (&builder, g_variant_deep_copy (child));
|
||||
g_variant_unref (child);
|
||||
}
|
||||
--
|
||||
2.24.4
|
||||
|
||||
394
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
Normal file
394
meta/recipes-core/glib-2.0/glib-2.0/CVE-2023-32665-0008.patch
Normal file
@@ -0,0 +1,394 @@
|
||||
From d1a293c4e29880b8d17bb826c9a426a440ca4a91 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 17 Aug 2023 01:30:38 +0000
|
||||
Subject: [PATCH] gvariant: Track checked and ordered offsets independently
|
||||
|
||||
The past few commits introduced the concept of known-good offsets in the
|
||||
offset table (which is used for variable-width arrays and tuples).
|
||||
Good offsets are ones which are non-overlapping with all the previous
|
||||
offsets in the table.
|
||||
|
||||
If a bad offset is encountered when indexing into the array or tuple,
|
||||
the cached known-good offset index will not be increased. In this way,
|
||||
all child variants at and beyond the first bad offset can be returned as
|
||||
default values rather than dereferencing potentially invalid data.
|
||||
|
||||
In this case, there was no information about the fact that the indexes
|
||||
between the highest known-good index and the requested one had been
|
||||
checked already. That could lead to a pathological case where an offset
|
||||
table with an invalid first offset is repeatedly checked in full when
|
||||
trying to access higher-indexed children.
|
||||
|
||||
Avoid that by storing the index of the highest checked offset in the
|
||||
table, as well as the index of the highest good/ordered offset.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/d1a293c4e29880b8d17bb826c9a426a440ca4a91]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant-core.c | 28 ++++++++++++++++++++++++
|
||||
glib/gvariant-serialiser.c | 44 +++++++++++++++++++++++++++-----------
|
||||
glib/gvariant-serialiser.h | 9 ++++++++
|
||||
glib/gvariant.c | 1 +
|
||||
glib/tests/gvariant.c | 5 +++++
|
||||
5 files changed, 75 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
|
||||
index b951cd9..1b9d5cc 100644
|
||||
--- a/glib/gvariant-core.c
|
||||
+++ b/glib/gvariant-core.c
|
||||
@@ -67,6 +67,7 @@ struct _GVariant
|
||||
GBytes *bytes;
|
||||
gconstpointer data;
|
||||
gsize ordered_offsets_up_to;
|
||||
+ gsize checked_offsets_up_to;
|
||||
} serialised;
|
||||
|
||||
struct
|
||||
@@ -182,6 +183,24 @@ struct _GVariant
|
||||
* This field is only relevant for arrays of non
|
||||
* fixed width types and for tuples.
|
||||
*
|
||||
+ * .checked_offsets_up_to: Similarly to .ordered_offsets_up_to, this stores
|
||||
+ * the index of the highest element, n, whose frame
|
||||
+ * offsets (and all the preceding frame offsets)
|
||||
+ * have been checked for validity.
|
||||
+ *
|
||||
+ * It is always the case that
|
||||
+ * .checked_offsets_up_to ≥ .ordered_offsets_up_to.
|
||||
+ *
|
||||
+ * If .checked_offsets_up_to == .ordered_offsets_up_to,
|
||||
+ * then a bad offset has not been found so far.
|
||||
+ *
|
||||
+ * If .checked_offsets_up_to > .ordered_offsets_up_to,
|
||||
+ * then a bad offset has been found at
|
||||
+ * (.ordered_offsets_up_to + 1).
|
||||
+ *
|
||||
+ * This field is only relevant for arrays of non
|
||||
+ * fixed width types and for tuples.
|
||||
+ *
|
||||
* .tree: Only valid when the instance is in tree form.
|
||||
*
|
||||
* Note that accesses from other threads could result in
|
||||
@@ -386,6 +405,7 @@ g_variant_to_serialised (GVariant *value)
|
||||
value->size,
|
||||
value->depth,
|
||||
value->contents.serialised.ordered_offsets_up_to,
|
||||
+ value->contents.serialised.checked_offsets_up_to,
|
||||
};
|
||||
return serialised;
|
||||
}
|
||||
@@ -418,6 +438,7 @@ g_variant_serialise (GVariant *value,
|
||||
serialised.data = data;
|
||||
serialised.depth = value->depth;
|
||||
serialised.ordered_offsets_up_to = 0;
|
||||
+ serialised.checked_offsets_up_to = 0;
|
||||
|
||||
children = (gpointer *) value->contents.tree.children;
|
||||
n_children = value->contents.tree.n_children;
|
||||
@@ -464,10 +485,12 @@ g_variant_fill_gvs (GVariantSerialised *serialised,
|
||||
if (value->state & STATE_SERIALISED)
|
||||
{
|
||||
serialised->ordered_offsets_up_to = value->contents.serialised.ordered_offsets_up_to;
|
||||
+ serialised->checked_offsets_up_to = value->contents.serialised.checked_offsets_up_to;
|
||||
}
|
||||
else
|
||||
{
|
||||
serialised->ordered_offsets_up_to = 0;
|
||||
+ serialised->checked_offsets_up_to = 0;
|
||||
}
|
||||
|
||||
if (serialised->data)
|
||||
@@ -513,6 +536,7 @@ g_variant_ensure_serialised (GVariant *value)
|
||||
value->contents.serialised.data = g_bytes_get_data (bytes, NULL);
|
||||
value->contents.serialised.bytes = bytes;
|
||||
value->contents.serialised.ordered_offsets_up_to = G_MAXSIZE;
|
||||
+ value->contents.serialised.checked_offsets_up_to = G_MAXSIZE;
|
||||
value->state |= STATE_SERIALISED;
|
||||
}
|
||||
}
|
||||
@@ -594,6 +618,7 @@ g_variant_new_from_bytes (const GVariantType *type,
|
||||
serialised.data = (guchar *) g_bytes_get_data (bytes, &serialised.size);
|
||||
serialised.depth = 0;
|
||||
serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
+ serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
|
||||
if (!g_variant_serialised_check (serialised))
|
||||
{
|
||||
@@ -644,6 +669,7 @@ g_variant_new_from_bytes (const GVariantType *type,
|
||||
}
|
||||
|
||||
value->contents.serialised.ordered_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
+ value->contents.serialised.checked_offsets_up_to = trusted ? G_MAXSIZE : 0;
|
||||
|
||||
g_clear_pointer (&owned_bytes, g_bytes_unref);
|
||||
|
||||
@@ -1120,6 +1146,7 @@ g_variant_get_child_value (GVariant *value,
|
||||
|
||||
/* Update the cached ordered_offsets_up_to, since @serialised will be thrown away when this function exits */
|
||||
value->contents.serialised.ordered_offsets_up_to = MAX (value->contents.serialised.ordered_offsets_up_to, serialised.ordered_offsets_up_to);
|
||||
+ value->contents.serialised.checked_offsets_up_to = MAX (value->contents.serialised.checked_offsets_up_to, serialised.checked_offsets_up_to);
|
||||
|
||||
/* Check whether this would cause nesting too deep. If so, return a fake
|
||||
* child. The only situation we expect this to happen in is with a variant,
|
||||
@@ -1147,6 +1174,7 @@ g_variant_get_child_value (GVariant *value,
|
||||
g_bytes_ref (value->contents.serialised.bytes);
|
||||
child->contents.serialised.data = s_child.data;
|
||||
child->contents.serialised.ordered_offsets_up_to = s_child.ordered_offsets_up_to;
|
||||
+ child->contents.serialised.checked_offsets_up_to = s_child.checked_offsets_up_to;
|
||||
|
||||
return child;
|
||||
}
|
||||
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
|
||||
index cd4a3e6..0bf7243 100644
|
||||
--- a/glib/gvariant-serialiser.c
|
||||
+++ b/glib/gvariant-serialiser.c
|
||||
@@ -120,6 +120,8 @@
|
||||
*
|
||||
* @depth has no restrictions; the depth of a top-level serialised #GVariant is
|
||||
* zero, and it increases for each level of nested child.
|
||||
+ *
|
||||
+ * @checked_offsets_up_to is always ≥ @ordered_offsets_up_to
|
||||
*/
|
||||
|
||||
/* < private >
|
||||
@@ -147,6 +149,9 @@ g_variant_serialised_check (GVariantSerialised serialised)
|
||||
!(serialised.size == 0 || serialised.data != NULL))
|
||||
return FALSE;
|
||||
|
||||
+ if (serialised.ordered_offsets_up_to > serialised.checked_offsets_up_to)
|
||||
+ return FALSE;
|
||||
+
|
||||
/* Depending on the native alignment requirements of the machine, the
|
||||
* compiler will insert either 3 or 7 padding bytes after the char.
|
||||
* This will result in the sizeof() the struct being 12 or 16.
|
||||
@@ -266,6 +271,7 @@ gvs_fixed_sized_maybe_get_child (GVariantSerialised value,
|
||||
g_variant_type_info_ref (value.type_info);
|
||||
value.depth++;
|
||||
value.ordered_offsets_up_to = 0;
|
||||
+ value.checked_offsets_up_to = 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -297,7 +303,7 @@ gvs_fixed_sized_maybe_serialise (GVariantSerialised value,
|
||||
{
|
||||
if (n_children)
|
||||
{
|
||||
- GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0 };
|
||||
+ GVariantSerialised child = { NULL, value.data, value.size, value.depth + 1, 0, 0 };
|
||||
|
||||
gvs_filler (&child, children[0]);
|
||||
}
|
||||
@@ -320,6 +326,7 @@ gvs_fixed_sized_maybe_is_normal (GVariantSerialised value)
|
||||
value.type_info = g_variant_type_info_element (value.type_info);
|
||||
value.depth++;
|
||||
value.ordered_offsets_up_to = 0;
|
||||
+ value.checked_offsets_up_to = 0;
|
||||
|
||||
return g_variant_serialised_is_normal (value);
|
||||
}
|
||||
@@ -362,6 +369,7 @@ gvs_variable_sized_maybe_get_child (GVariantSerialised value,
|
||||
|
||||
value.depth++;
|
||||
value.ordered_offsets_up_to = 0;
|
||||
+ value.checked_offsets_up_to = 0;
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -392,7 +400,7 @@ gvs_variable_sized_maybe_serialise (GVariantSerialised value,
|
||||
{
|
||||
if (n_children)
|
||||
{
|
||||
- GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0 };
|
||||
+ GVariantSerialised child = { NULL, value.data, value.size - 1, value.depth + 1, 0, 0 };
|
||||
|
||||
/* write the data for the child. */
|
||||
gvs_filler (&child, children[0]);
|
||||
@@ -413,6 +421,7 @@ gvs_variable_sized_maybe_is_normal (GVariantSerialised value)
|
||||
value.size--;
|
||||
value.depth++;
|
||||
value.ordered_offsets_up_to = 0;
|
||||
+ value.checked_offsets_up_to = 0;
|
||||
|
||||
return g_variant_serialised_is_normal (value);
|
||||
}
|
||||
@@ -739,39 +748,46 @@ gvs_variable_sized_array_get_child (GVariantSerialised value,
|
||||
|
||||
/* If the requested @index_ is beyond the set of indices whose framing offsets
|
||||
* have been checked, check the remaining offsets to see whether they’re
|
||||
- * normal (in order, no overlapping array elements). */
|
||||
- if (index_ > value.ordered_offsets_up_to)
|
||||
+ * normal (in order, no overlapping array elements).
|
||||
+ *
|
||||
+ * Don’t bother checking if the highest known-good offset is lower than the
|
||||
+ * highest checked offset, as that means there’s an invalid element at that
|
||||
+ * index, so there’s no need to check further. */
|
||||
+ if (index_ > value.checked_offsets_up_to &&
|
||||
+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
|
||||
{
|
||||
switch (offsets.offset_size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
value.ordered_offsets_up_to = find_unordered_guint8 (
|
||||
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
value.ordered_offsets_up_to = find_unordered_guint16 (
|
||||
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
value.ordered_offsets_up_to = find_unordered_guint32 (
|
||||
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
value.ordered_offsets_up_to = find_unordered_guint64 (
|
||||
- offsets.array, value.ordered_offsets_up_to, index_ + 1);
|
||||
+ offsets.array, value.checked_offsets_up_to, index_ + 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* gvs_get_offset_size() only returns maximum 8 */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
+
|
||||
+ value.checked_offsets_up_to = index_;
|
||||
}
|
||||
|
||||
if (index_ > value.ordered_offsets_up_to)
|
||||
@@ -916,6 +932,7 @@ gvs_variable_sized_array_is_normal (GVariantSerialised value)
|
||||
|
||||
/* All offsets have now been checked. */
|
||||
value.ordered_offsets_up_to = G_MAXSIZE;
|
||||
+ value.checked_offsets_up_to = G_MAXSIZE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1040,14 +1057,15 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
* all the tuple *elements* here, not just all the framing offsets, since
|
||||
* tuples contain a mix of elements which use framing offsets and ones which
|
||||
* don’t. None of them are allowed to overlap. */
|
||||
- if (index_ > value.ordered_offsets_up_to)
|
||||
+ if (index_ > value.checked_offsets_up_to &&
|
||||
+ value.ordered_offsets_up_to == value.checked_offsets_up_to)
|
||||
{
|
||||
gsize i, prev_i_end = 0;
|
||||
|
||||
- if (value.ordered_offsets_up_to > 0)
|
||||
- gvs_tuple_get_member_bounds (value, value.ordered_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
|
||||
+ if (value.checked_offsets_up_to > 0)
|
||||
+ gvs_tuple_get_member_bounds (value, value.checked_offsets_up_to - 1, offset_size, NULL, &prev_i_end);
|
||||
|
||||
- for (i = value.ordered_offsets_up_to; i <= index_; i++)
|
||||
+ for (i = value.checked_offsets_up_to; i <= index_; i++)
|
||||
{
|
||||
gsize i_start, i_end;
|
||||
|
||||
@@ -1060,6 +1078,7 @@ gvs_tuple_get_child (GVariantSerialised value,
|
||||
}
|
||||
|
||||
value.ordered_offsets_up_to = i - 1;
|
||||
+ value.checked_offsets_up_to = index_;
|
||||
}
|
||||
|
||||
if (index_ > value.ordered_offsets_up_to)
|
||||
@@ -1257,6 +1276,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
|
||||
|
||||
/* All element bounds have been checked above. */
|
||||
value.ordered_offsets_up_to = G_MAXSIZE;
|
||||
+ value.checked_offsets_up_to = G_MAXSIZE;
|
||||
|
||||
{
|
||||
gsize fixed_size;
|
||||
diff --git a/glib/gvariant-serialiser.h b/glib/gvariant-serialiser.h
|
||||
index 144aec8..e132451 100644
|
||||
--- a/glib/gvariant-serialiser.h
|
||||
+++ b/glib/gvariant-serialiser.h
|
||||
@@ -40,6 +40,15 @@ typedef struct
|
||||
* Even when dealing with tuples, @ordered_offsets_up_to is an element index,
|
||||
* rather than an index into the frame offsets. */
|
||||
gsize ordered_offsets_up_to;
|
||||
+
|
||||
+ /* Similar to @ordered_offsets_up_to. This gives the index of the child element
|
||||
+ * whose frame offset is the highest in the offset table which has been
|
||||
+ * checked so far.
|
||||
+ *
|
||||
+ * This is always ≥ @ordered_offsets_up_to. It is always an element index.
|
||||
+ *
|
||||
+ * See documentation in gvariant-core.c for `struct GVariant` for details. */
|
||||
+ gsize checked_offsets_up_to;
|
||||
} GVariantSerialised;
|
||||
|
||||
/* deserialisation */
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index fdd36be..f910bd4 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5945,6 +5945,7 @@ g_variant_byteswap (GVariant *value)
|
||||
serialised.size = g_variant_get_size (trusted);
|
||||
serialised.data = g_malloc (serialised.size);
|
||||
serialised.ordered_offsets_up_to = G_MAXSIZE; /* operating on the normal form */
|
||||
+ serialised.checked_offsets_up_to = G_MAXSIZE;
|
||||
g_variant_store (trusted, serialised.data);
|
||||
g_variant_unref (trusted);
|
||||
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index a84b02e..640f3c0 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -1286,6 +1286,7 @@ random_instance_filler (GVariantSerialised *serialised,
|
||||
|
||||
serialised->depth = 0;
|
||||
serialised->ordered_offsets_up_to = 0;
|
||||
+ serialised->checked_offsets_up_to = 0;
|
||||
|
||||
g_assert_true (serialised->type_info == instance->type_info);
|
||||
g_assert_cmpuint (serialised->size, ==, instance->size);
|
||||
@@ -1453,6 +1454,7 @@ test_maybe (void)
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
serialised.ordered_offsets_up_to = 0;
|
||||
+ serialised.checked_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised,
|
||||
random_instance_filler,
|
||||
@@ -1577,6 +1579,7 @@ test_array (void)
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
serialised.ordered_offsets_up_to = 0;
|
||||
+ serialised.checked_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) instances, n_children);
|
||||
@@ -1742,6 +1745,7 @@ test_tuple (void)
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
serialised.ordered_offsets_up_to = 0;
|
||||
+ serialised.checked_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) instances, n_children);
|
||||
@@ -1839,6 +1843,7 @@ test_variant (void)
|
||||
serialised.size = needed_size;
|
||||
serialised.depth = 0;
|
||||
serialised.ordered_offsets_up_to = 0;
|
||||
+ serialised.checked_offsets_up_to = 0;
|
||||
|
||||
g_variant_serialiser_serialise (serialised, random_instance_filler,
|
||||
(gpointer *) &instance, 1);
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
From 298a537d5f6783e55d87e40011ee3fd3b22b72f9 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Withnall <pwithnall@endlessos.org>
|
||||
Date: Thu, 17 Aug 2023 01:39:01 +0000
|
||||
Subject: [PATCH] gvariant: Zero-initialise various GVariantSerialised objects
|
||||
|
||||
The following few commits will add a couple of new fields to
|
||||
`GVariantSerialised`, and they should be zero-filled by default.
|
||||
|
||||
Try and pre-empt that a bit by zero-filling `GVariantSerialised` by
|
||||
default in a few places.
|
||||
|
||||
Signed-off-by: Philip Withnall <pwithnall@endlessos.org>
|
||||
|
||||
Helps: #2121
|
||||
|
||||
CVE: CVE-2023-32665
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/glib/-/commit/298a537d5f6783e55d87e40011ee3fd3b22b72f9]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
glib/gvariant.c | 2 +-
|
||||
glib/tests/gvariant.c | 12 ++++++------
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/glib/gvariant.c b/glib/gvariant.c
|
||||
index f910bd4..8ba701e 100644
|
||||
--- a/glib/gvariant.c
|
||||
+++ b/glib/gvariant.c
|
||||
@@ -5936,7 +5936,7 @@ g_variant_byteswap (GVariant *value)
|
||||
if (alignment)
|
||||
/* (potentially) contains multi-byte numeric data */
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
GVariant *trusted;
|
||||
GBytes *bytes;
|
||||
|
||||
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
|
||||
index 640f3c0..d640c81 100644
|
||||
--- a/glib/tests/gvariant.c
|
||||
+++ b/glib/tests/gvariant.c
|
||||
@@ -1446,7 +1446,7 @@ test_maybe (void)
|
||||
|
||||
for (flavour = 0; flavour < 8; flavour += alignment)
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
GVariantSerialised child;
|
||||
|
||||
serialised.type_info = type_info;
|
||||
@@ -1572,7 +1572,7 @@ test_array (void)
|
||||
|
||||
for (flavour = 0; flavour < 8; flavour += alignment)
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
|
||||
serialised.type_info = array_info;
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
@@ -1738,7 +1738,7 @@ test_tuple (void)
|
||||
|
||||
for (flavour = 0; flavour < 8; flavour += alignment)
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
|
||||
serialised.type_info = type_info;
|
||||
serialised.data = flavoured_malloc (needed_size, flavour);
|
||||
@@ -1835,7 +1835,7 @@ test_variant (void)
|
||||
|
||||
for (flavour = 0; flavour < 8; flavour += alignment)
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
GVariantSerialised child;
|
||||
|
||||
serialised.type_info = type_info;
|
||||
@@ -2284,7 +2284,7 @@ serialise_tree (TreeInstance *tree,
|
||||
static void
|
||||
test_byteswap (void)
|
||||
{
|
||||
- GVariantSerialised one, two;
|
||||
+ GVariantSerialised one = { 0, }, two = { 0, };
|
||||
TreeInstance *tree;
|
||||
|
||||
tree = tree_instance_new (NULL, 3);
|
||||
@@ -2358,7 +2358,7 @@ test_serialiser_children (void)
|
||||
static void
|
||||
test_fuzz (gdouble *fuzziness)
|
||||
{
|
||||
- GVariantSerialised serialised;
|
||||
+ GVariantSerialised serialised = { 0, };
|
||||
TreeInstance *tree;
|
||||
|
||||
/* make an instance */
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -42,6 +42,20 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
|
||||
file://CVE-2021-28153-3.patch \
|
||||
file://CVE-2021-28153-4.patch \
|
||||
file://CVE-2021-28153-5.patch \
|
||||
file://CVE-2023-32665-0001.patch \
|
||||
file://CVE-2023-32665-0002.patch \
|
||||
file://CVE-2023-32665-0003.patch \
|
||||
file://CVE-2023-32665-0004.patch \
|
||||
file://CVE-2023-32665-0005.patch \
|
||||
file://CVE-2023-32665-0006.patch \
|
||||
file://CVE-2023-32665-0007.patch \
|
||||
file://CVE-2023-32665-0008.patch \
|
||||
file://CVE-2023-32665-0009.patch \
|
||||
file://CVE-2023-29499.patch \
|
||||
file://CVE-2023-32611-0001.patch \
|
||||
file://CVE-2023-32611-0002.patch \
|
||||
file://CVE-2023-32643.patch \
|
||||
file://CVE-2023-32636.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_class-native = " file://relocate-modules.patch"
|
||||
|
||||
63
meta/recipes-core/glibc/glibc/CVE-2023-4911.patch
Normal file
63
meta/recipes-core/glibc/glibc/CVE-2023-4911.patch
Normal file
@@ -0,0 +1,63 @@
|
||||
From d2b77337f734fcacdfc8e0ddec14cf31a746c7be Mon Sep 17 00:00:00 2001
|
||||
From: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Mon, 11 Sep 2023 18:53:15 -0400
|
||||
Subject: [PATCH v2] tunables: Terminate immediately if end of input is reached
|
||||
|
||||
The string parsing routine may end up writing beyond bounds of tunestr
|
||||
if the input tunable string is malformed, of the form name=name=val.
|
||||
This gets processed twice, first as name=name=val and next as name=val,
|
||||
resulting in tunestr being name=name=val:name=val, thus overflowing
|
||||
tunestr.
|
||||
|
||||
Terminate the parsing loop at the first instance itself so that tunestr
|
||||
does not overflow.
|
||||
---
|
||||
Changes from v1:
|
||||
|
||||
- Also null-terminate tunestr before exiting.
|
||||
|
||||
elf/dl-tunables.c | 17 ++++++++++-------
|
||||
1 file changed, 10 insertions(+), 7 deletions(-)
|
||||
|
||||
Upstream-Status: Backport [git://sourceware.org/git/glibc.git]
|
||||
CVE: CVE-2023-4911
|
||||
|
||||
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
|
||||
index 8e7ee9df10..76cf8b9da3 100644
|
||||
--- a/elf/dl-tunables.c
|
||||
+++ b/elf/dl-tunables.c
|
||||
@@ -187,11 +187,7 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
/* If we reach the end of the string before getting a valid name-value
|
||||
pair, bail out. */
|
||||
if (p[len] == '\0')
|
||||
- {
|
||||
- if (__libc_enable_secure)
|
||||
- tunestr[off] = '\0';
|
||||
- return;
|
||||
- }
|
||||
+ break;
|
||||
|
||||
/* We did not find a valid name-value pair before encountering the
|
||||
colon. */
|
||||
@@ -251,9 +247,16 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
}
|
||||
}
|
||||
|
||||
- if (p[len] != '\0')
|
||||
- p += len + 1;
|
||||
+ /* We reached the end while processing the tunable string. */
|
||||
+ if (p[len] == '\0')
|
||||
+ break;
|
||||
+
|
||||
+ p += len + 1;
|
||||
}
|
||||
+
|
||||
+ /* Terminate tunestr before we leave. */
|
||||
+ if (__libc_enable_secure)
|
||||
+ tunestr[off] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
||||
@@ -58,7 +58,7 @@ elif targettype == "ssh":
|
||||
user = os.environ.get("SSH_HOST_USER", None)
|
||||
port = os.environ.get("SSH_HOST_PORT", None)
|
||||
|
||||
command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no"]
|
||||
command = ["ssh", "-o", "UserKnownHostsFile=/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=quiet"]
|
||||
if port:
|
||||
command += ["-p", str(port)]
|
||||
if not host:
|
||||
|
||||
@@ -29,6 +29,13 @@ CVE_CHECK_WHITELIST += "CVE-2019-1010025"
|
||||
# https://git.yoctoproject.org/cgit/cgit.cgi/poky/commit/?h=dunfell&id=e1e89ff7d75c3d2223f9e3bd875b9b0c5e15836b
|
||||
CVE_CHECK_WHITELIST += "CVE-2021-35942"
|
||||
|
||||
# glibc https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2023-4527
|
||||
# This vulnerability was introduced in 2.36 by commit
|
||||
# f282cdbe7f436c75864e5640a409a10485e9abb2 resolv: Implement no-aaaa stub resolver option
|
||||
# so our version is not yet vulnerable
|
||||
# See https://sourceware.org/bugzilla/show_bug.cgi?id=30842
|
||||
CVE_CHECK_WHITELIST += "CVE-2023-4527"
|
||||
|
||||
DEPENDS += "gperf-native bison-native make-native"
|
||||
|
||||
NATIVESDKFIXES ?= ""
|
||||
@@ -80,6 +87,7 @@ SRC_URI = "${GLIBC_GIT_URI};branch=${SRCBRANCH};name=glibc \
|
||||
file://0036-i386-Avoid-lazy-relocation-of-tlsdesc-BZ-27137.patch \
|
||||
file://0037-Avoid-deadlock-between-pthread_create-and-ctors.patch \
|
||||
file://CVE-2023-0687.patch \
|
||||
file://CVE-2023-4911.patch \
|
||||
"
|
||||
S = "${WORKDIR}/git"
|
||||
B = "${WORKDIR}/build-${TARGET_SYS}"
|
||||
|
||||
@@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk"
|
||||
|
||||
inherit core-image setuptools3
|
||||
|
||||
SRCREV ?= "88bec50206d02fef3cdc3eaabb638963144eb63b"
|
||||
SRCREV ?= "b86bf0103c5d5ee04012473b80353e3da1f9e67f"
|
||||
SRC_URI = "git://git.yoctoproject.org/poky;branch=dunfell \
|
||||
file://Yocto_Build_Appliance.vmx \
|
||||
file://Yocto_Build_Appliance.vmxf \
|
||||
|
||||
36
meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch
Normal file
36
meta/recipes-core/libxml/libxml2/CVE-2023-39615-0001.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From d0c3f01e110d54415611c5fa0040cdf4a56053f9 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Sat, 6 May 2023 17:47:37 +0200
|
||||
Subject: [PATCH] parser: Fix old SAX1 parser with custom callbacks
|
||||
|
||||
For some reason, xmlCtxtUseOptionsInternal set the start and end element
|
||||
SAX handlers to the internal DOM builder functions when XML_PARSE_SAX1
|
||||
was specified. This means that custom SAX handlers could never work with
|
||||
that flag because these functions would receive the wrong user data
|
||||
argument and crash immediately.
|
||||
|
||||
Fixes #535.
|
||||
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/d0c3f01e110d54415611c5fa0040cdf4a56053f9]
|
||||
CVE: CVE-2023-39615
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
parser.c | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 6e09208..7814e6e 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -15156,8 +15156,6 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi
|
||||
}
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
if (options & XML_PARSE_SAX1) {
|
||||
- ctxt->sax->startElement = xmlSAX2StartElement;
|
||||
- ctxt->sax->endElement = xmlSAX2EndElement;
|
||||
ctxt->sax->startElementNs = NULL;
|
||||
ctxt->sax->endElementNs = NULL;
|
||||
ctxt->sax->initialized = 1;
|
||||
--
|
||||
2.24.4
|
||||
|
||||
71
meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch
Normal file
71
meta/recipes-core/libxml/libxml2/CVE-2023-39615-0002.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
From 235b15a590eecf97b09e87bdb7e4f8333e9de129 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Mon, 8 May 2023 17:58:02 +0200
|
||||
Subject: [PATCH] SAX: Always initialize SAX1 element handlers
|
||||
|
||||
Follow-up to commit d0c3f01e. A parser context will be initialized to
|
||||
SAX version 2, but this can be overridden with XML_PARSE_SAX1 later,
|
||||
so we must initialize the SAX1 element handlers as well.
|
||||
|
||||
Change the check in xmlDetectSAX2 to only look for XML_SAX2_MAGIC, so
|
||||
we don't switch to SAX1 if the SAX2 element handlers are NULL.
|
||||
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/235b15a590eecf97b09e87bdb7e4f8333e9de129]
|
||||
CVE: CVE-2023-39615
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
SAX2.c | 11 +++++++----
|
||||
parser.c | 5 +----
|
||||
2 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/SAX2.c b/SAX2.c
|
||||
index 5f141f9..902d34d 100644
|
||||
--- a/SAX2.c
|
||||
+++ b/SAX2.c
|
||||
@@ -2869,20 +2869,23 @@ xmlSAXVersion(xmlSAXHandler *hdlr, int version)
|
||||
{
|
||||
if (hdlr == NULL) return(-1);
|
||||
if (version == 2) {
|
||||
- hdlr->startElement = NULL;
|
||||
- hdlr->endElement = NULL;
|
||||
hdlr->startElementNs = xmlSAX2StartElementNs;
|
||||
hdlr->endElementNs = xmlSAX2EndElementNs;
|
||||
hdlr->serror = NULL;
|
||||
hdlr->initialized = XML_SAX2_MAGIC;
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
} else if (version == 1) {
|
||||
- hdlr->startElement = xmlSAX2StartElement;
|
||||
- hdlr->endElement = xmlSAX2EndElement;
|
||||
hdlr->initialized = 1;
|
||||
#endif /* LIBXML_SAX1_ENABLED */
|
||||
} else
|
||||
return(-1);
|
||||
+#ifdef LIBXML_SAX1_ENABLED
|
||||
+ hdlr->startElement = xmlSAX2StartElement;
|
||||
+ hdlr->endElement = xmlSAX2EndElement;
|
||||
+#else
|
||||
+ hdlr->startElement = NULL;
|
||||
+ hdlr->endElement = NULL;
|
||||
+#endif /* LIBXML_SAX1_ENABLED */
|
||||
hdlr->internalSubset = xmlSAX2InternalSubset;
|
||||
hdlr->externalSubset = xmlSAX2ExternalSubset;
|
||||
hdlr->isStandalone = xmlSAX2IsStandalone;
|
||||
diff --git a/parser.c b/parser.c
|
||||
index 7814e6e..cf0fb38 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -1102,10 +1102,7 @@ xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
|
||||
if (ctxt == NULL) return;
|
||||
sax = ctxt->sax;
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
- if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
|
||||
- ((sax->startElementNs != NULL) ||
|
||||
- (sax->endElementNs != NULL) ||
|
||||
- ((sax->startElement == NULL) && (sax->endElement == NULL))))
|
||||
+ if ((sax) && (sax->initialized == XML_SAX2_MAGIC))
|
||||
ctxt->sax2 = 1;
|
||||
#else
|
||||
ctxt->sax2 = 1;
|
||||
--
|
||||
2.24.4
|
||||
|
||||
44
meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch
Normal file
44
meta/recipes-core/libxml/libxml2/CVE-2023-39615-pre.patch
Normal file
@@ -0,0 +1,44 @@
|
||||
From 99fc048d7f7292c5ee18e44c400bd73bc63a47ed Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Fri, 14 Aug 2020 14:18:50 +0200
|
||||
Subject: [PATCH] Don't use SAX1 if all element handlers are NULL
|
||||
|
||||
Running xmllint with "--sax --noout" installs a SAX2 handler with all
|
||||
callbacks set to NULL. In this case or similar situations, we don't want
|
||||
to switch to SAX1 parsing.
|
||||
|
||||
Note: This patch is needed for "CVE-2023-39615-0002" patch to apply.
|
||||
Without this patch the build will fail with undefined sax error.
|
||||
|
||||
Upstream-Status: Backport from [https://gitlab.gnome.org/GNOME/libxml2/-/commit/99fc048d7f7292c5ee18e44c400bd73bc63a47ed]
|
||||
Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
|
||||
---
|
||||
parser.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/parser.c b/parser.c
|
||||
index bb677b0..6e09208 100644
|
||||
--- a/parser.c
|
||||
+++ b/parser.c
|
||||
@@ -1098,11 +1098,15 @@ xmlHasFeature(xmlFeature feature)
|
||||
*/
|
||||
static void
|
||||
xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
|
||||
+ xmlSAXHandlerPtr sax;
|
||||
if (ctxt == NULL) return;
|
||||
+ sax = ctxt->sax;
|
||||
#ifdef LIBXML_SAX1_ENABLED
|
||||
- if ((ctxt->sax) && (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
|
||||
- ((ctxt->sax->startElementNs != NULL) ||
|
||||
- (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
|
||||
+ if ((sax) && (sax->initialized == XML_SAX2_MAGIC) &&
|
||||
+ ((sax->startElementNs != NULL) ||
|
||||
+ (sax->endElementNs != NULL) ||
|
||||
+ ((sax->startElement == NULL) && (sax->endElement == NULL))))
|
||||
+ ctxt->sax2 = 1;
|
||||
#else
|
||||
ctxt->sax2 = 1;
|
||||
#endif /* LIBXML_SAX1_ENABLED */
|
||||
--
|
||||
2.24.4
|
||||
|
||||
@@ -38,6 +38,9 @@ SRC_URI += "http://www.w3.org/XML/Test/xmlts20080827.tar.gz;subdir=${BP};name=te
|
||||
file://CVE-2022-40304.patch \
|
||||
file://CVE-2023-28484.patch \
|
||||
file://CVE-2023-29469.patch \
|
||||
file://CVE-2023-39615-pre.patch \
|
||||
file://CVE-2023-39615-0001.patch \
|
||||
file://CVE-2023-39615-0002.patch \
|
||||
"
|
||||
|
||||
SRC_URI[archive.sha256sum] = "593b7b751dd18c2d6abcd0c4bcb29efc203d0b4373a6df98e3a455ea74ae2813"
|
||||
|
||||
@@ -136,7 +136,7 @@ def nvd_request_next(url, api_key, args):
|
||||
|
||||
if (r.headers['content-encoding'] == 'gzip'):
|
||||
buf = r.read()
|
||||
raw_data = gzip.decompress(buf)
|
||||
raw_data = gzip.decompress(buf).decode("utf-8")
|
||||
else:
|
||||
raw_data = r.read().decode("utf-8")
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ class SystemdUnit():
|
||||
try:
|
||||
for dependent in config.get('Install', prop):
|
||||
# expand any %i to instance (ignoring escape sequence %%)
|
||||
dependent = re.sub("([^%](%%)*)%i", "\\1{}".format(instance), dependent)
|
||||
dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(instance), dependent)
|
||||
wants = systemdir / "{}.{}".format(dependent, dirstem) / service
|
||||
add_link(wants, target)
|
||||
|
||||
|
||||
120
meta/recipes-core/systemd/systemd/CVE-2018-21029.patch
Normal file
120
meta/recipes-core/systemd/systemd/CVE-2018-21029.patch
Normal file
@@ -0,0 +1,120 @@
|
||||
From 3f9d9289ee8730a81a0464539f4e1ba2d23d0ce9 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= <joerg@thalheim.io>
|
||||
Date: Tue, 3 Mar 2020 23:31:25 +0000
|
||||
Subject: [PATCH] systemd-resolved: use hostname for certificate validation in
|
||||
DoT
|
||||
|
||||
Widely accepted certificates for IP addresses are expensive and only
|
||||
affordable for larger organizations. Therefore if the user provides
|
||||
the hostname in the DNS= option, we should use it instead of the IP
|
||||
address.
|
||||
|
||||
(cherry picked from commit eec394f10bbfcc3d2fc8504ad8ff5be44231abd5)
|
||||
|
||||
CVE: CVE-2018-21029
|
||||
Upstream-Status: Backport [ff26d281aec0877b43269f18c6282cd79a7f5529]
|
||||
Signed-off-by: Marek Vasut <marex@denx.de>
|
||||
---
|
||||
man/resolved.conf.xml | 16 +++++++++++-----
|
||||
src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++--------
|
||||
src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++----
|
||||
3 files changed, 34 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml
|
||||
index 818000145b..37161ebcbc 100644
|
||||
--- a/man/resolved.conf.xml
|
||||
+++ b/man/resolved.conf.xml
|
||||
@@ -193,11 +193,17 @@
|
||||
<varlistentry>
|
||||
<term><varname>DNSOverTLS=</varname></term>
|
||||
<listitem>
|
||||
- <para>Takes a boolean argument or <literal>opportunistic</literal>.
|
||||
- If true all connections to the server will be encrypted. Note that
|
||||
- this mode requires a DNS server that supports DNS-over-TLS and has
|
||||
- a valid certificate for it's IP. If the DNS server does not support
|
||||
- DNS-over-TLS all DNS requests will fail. When set to <literal>opportunistic</literal>
|
||||
+ <para>Takes a boolean argument or <literal>opportunistic</literal>. If
|
||||
+ true all connections to the server will be encrypted. Note that this
|
||||
+ mode requires a DNS server that supports DNS-over-TLS and has a valid
|
||||
+ certificate. If the hostname was specified in <varname>DNS=</varname>
|
||||
+ by using the format format <literal>address#server_name</literal> it
|
||||
+ is used to validate its certificate and also to enable Server Name
|
||||
+ Indication (SNI) when opening a TLS connection. Otherwise
|
||||
+ the certificate is checked against the server's IP.
|
||||
+ If the DNS server does not support DNS-over-TLS all DNS requests will fail.</para>
|
||||
+
|
||||
+ <para>When set to <literal>opportunistic</literal>
|
||||
DNS request are attempted to send encrypted with DNS-over-TLS.
|
||||
If the DNS server does not support TLS, DNS-over-TLS is disabled.
|
||||
Note that this mode makes DNS-over-TLS vulnerable to "downgrade"
|
||||
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c
|
||||
index ed0a31e8bf..c7215723a7 100644
|
||||
--- a/src/resolve/resolved-dnstls-gnutls.c
|
||||
+++ b/src/resolve/resolved-dnstls-gnutls.c
|
||||
@@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
|
||||
}
|
||||
|
||||
if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
|
||||
- stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
|
||||
- if (server->family == AF_INET) {
|
||||
- stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
|
||||
- stream->dnstls_data.validation.size = 4;
|
||||
- } else {
|
||||
- stream->dnstls_data.validation.data = server->address.in6.s6_addr;
|
||||
- stream->dnstls_data.validation.size = 16;
|
||||
+ if (server->server_name)
|
||||
+ gnutls_session_set_verify_cert(gs, server->server_name, 0);
|
||||
+ else {
|
||||
+ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS;
|
||||
+ if (server->family == AF_INET) {
|
||||
+ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr;
|
||||
+ stream->dnstls_data.validation.size = 4;
|
||||
+ } else {
|
||||
+ stream->dnstls_data.validation.data = server->address.in6.s6_addr;
|
||||
+ stream->dnstls_data.validation.size = 16;
|
||||
+ }
|
||||
+ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
|
||||
}
|
||||
- gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0);
|
||||
}
|
||||
|
||||
gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
|
||||
diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c
|
||||
index 85e202ff74..007aedaa5b 100644
|
||||
--- a/src/resolve/resolved-dnstls-openssl.c
|
||||
+++ b/src/resolve/resolved-dnstls-openssl.c
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
+#include <openssl/x509v3.h>
|
||||
|
||||
#include "io-util.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
@@ -78,13 +79,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
|
||||
|
||||
if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) {
|
||||
X509_VERIFY_PARAM *v;
|
||||
- const unsigned char *ip;
|
||||
|
||||
SSL_set_verify(s, SSL_VERIFY_PEER, NULL);
|
||||
v = SSL_get0_param(s);
|
||||
- ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr;
|
||||
- if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)))
|
||||
- return -ECONNREFUSED;
|
||||
+ if (server->server_name) {
|
||||
+ X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
+ if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0)
|
||||
+ return -ECONNREFUSED;
|
||||
+ } else {
|
||||
+ const unsigned char *ip;
|
||||
+ ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr;
|
||||
+ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0)
|
||||
+ return -ECONNREFUSED;
|
||||
+ }
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
--
|
||||
2.40.1
|
||||
|
||||
@@ -31,6 +31,7 @@ SRC_URI += "file://touchscreen.rules \
|
||||
file://network-fix-Link-reference-counter-issue.patch \
|
||||
file://rm-rf-refactor-rm-rf-children-split-out-body-of-directory.patch \
|
||||
file://rm-rf-optionally-fsync-after-removing-directory-tree.patch \
|
||||
file://CVE-2018-21029.patch \
|
||||
file://CVE-2021-3997-1.patch \
|
||||
file://CVE-2021-3997-2.patch \
|
||||
file://CVE-2021-3997-3.patch \
|
||||
|
||||
40
meta/recipes-core/zlib/zlib/CVE-2023-45853.patch
Normal file
40
meta/recipes-core/zlib/zlib/CVE-2023-45853.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 73331a6a0481067628f065ffe87bb1d8f787d10c Mon Sep 17 00:00:00 2001
|
||||
From: Hans Wennborg <hans@chromium.org>
|
||||
Date: Fri, 18 Aug 2023 11:05:33 +0200
|
||||
Subject: [PATCH] Reject overflows of zip header fields in minizip.
|
||||
|
||||
This checks the lengths of the file name, extra field, and comment
|
||||
that would be put in the zip headers, and rejects them if they are
|
||||
too long. They are each limited to 65535 bytes in length by the zip
|
||||
format. This also avoids possible buffer overflows if the provided
|
||||
fields are too long.
|
||||
|
||||
Upstream-Status: Backport from [https://github.com/madler/zlib/commit/73331a6a0481067628f065ffe87bb1d8f787d10c]
|
||||
CVE: CVE-2023-45853
|
||||
Signed-off-by: Ashish Sharma <asharma@mvista.com>
|
||||
---
|
||||
contrib/minizip/zip.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c
|
||||
index 3d3d4cadd..0446109b2 100644
|
||||
--- a/contrib/minizip/zip.c
|
||||
+++ b/contrib/minizip/zip.c
|
||||
@@ -1043,6 +1043,17 @@ extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, c
|
||||
return ZIP_PARAMERROR;
|
||||
#endif
|
||||
|
||||
+ // The filename and comment length must fit in 16 bits.
|
||||
+ if ((filename!=NULL) && (strlen(filename)>0xffff))
|
||||
+ return ZIP_PARAMERROR;
|
||||
+ if ((comment!=NULL) && (strlen(comment)>0xffff))
|
||||
+ return ZIP_PARAMERROR;
|
||||
+ // The extra field length must fit in 16 bits. If the member also requires
|
||||
+ // a Zip64 extra block, that will also need to fit within that 16-bit
|
||||
+ // length, but that will be checked for later.
|
||||
+ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
|
||||
+ return ZIP_PARAMERROR;
|
||||
+
|
||||
zi = (zip64_internal*)file;
|
||||
|
||||
if (zi->in_opened_file_inzip == 1)
|
||||
@@ -11,6 +11,7 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \
|
||||
file://CVE-2018-25032.patch \
|
||||
file://run-ptest \
|
||||
file://CVE-2022-37434.patch \
|
||||
file://CVE-2023-45853.patch \
|
||||
"
|
||||
UPSTREAM_CHECK_URI = "http://zlib.net/"
|
||||
|
||||
|
||||
@@ -53,5 +53,7 @@ SRC_URI = "\
|
||||
file://CVE-2020-16593.patch \
|
||||
file://0001-CVE-2021-45078.patch \
|
||||
file://CVE-2022-38533.patch \
|
||||
file://CVE-2023-25588.patch \
|
||||
file://CVE-2021-46174.patch \
|
||||
"
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
35
meta/recipes-devtools/binutils/binutils/CVE-2021-46174.patch
Normal file
35
meta/recipes-devtools/binutils/binutils/CVE-2021-46174.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From 46322722ad40ac1a75672ae0f62f4969195f1368 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Thu, 20 Jan 2022 13:58:38 +1030
|
||||
Subject: [PATCH] PR28753, buffer overflow in read_section_stabs_debugging_info
|
||||
|
||||
PR 28753
|
||||
* rddbg.c (read_section_stabs_debugging_info): Don't read past
|
||||
end of section when concatentating stab strings.
|
||||
|
||||
CVE: CVE-2021-46174
|
||||
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cad4d6b91e97]
|
||||
|
||||
(cherry picked from commit 085b299b71721e15f5c5c5344dc3e4e4536dadba)
|
||||
(cherry picked from commit cad4d6b91e97b6962807d33c04ed7e7797788438)
|
||||
Signed-off-by: poojitha adireddy <pooadire@cisco.com>
|
||||
---
|
||||
binutils/rddbg.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/binutils/rddbg.c b/binutils/rddbg.c
|
||||
index 72e934055b5..5e76d94a3c4 100644
|
||||
--- a/binutils/rddbg.c
|
||||
+++ b/binutils/rddbg.c
|
||||
@@ -207,7 +207,7 @@ read_section_stabs_debugging_info (bfd *abfd, asymbol **syms, long symcount,
|
||||
an attempt to read the byte before 'strings' would occur. */
|
||||
while ((len = strlen (s)) > 0
|
||||
&& s[len - 1] == '\\'
|
||||
- && stab + 12 < stabs + stabsize)
|
||||
+ && stab + 16 <= stabs + stabsize)
|
||||
{
|
||||
char *p;
|
||||
|
||||
--
|
||||
2.23.1
|
||||
|
||||
149
meta/recipes-devtools/binutils/binutils/CVE-2023-25588.patch
Normal file
149
meta/recipes-devtools/binutils/binutils/CVE-2023-25588.patch
Normal file
@@ -0,0 +1,149 @@
|
||||
From d12f8998d2d086f0a6606589e5aedb7147e6f2f1 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Modra <amodra@gmail.com>
|
||||
Date: Fri, 14 Oct 2022 10:30:21 +1030
|
||||
Subject: [PATCH] PR29677, Field `the_bfd` of `asymbol` is uninitialised
|
||||
|
||||
Besides not initialising the_bfd of synthetic symbols, counting
|
||||
symbols when sizing didn't match symbols created if there were any
|
||||
dynsyms named "". We don't want synthetic symbols without names
|
||||
anyway, so get rid of them. Also, simplify and correct sanity checks.
|
||||
|
||||
PR 29677
|
||||
* mach-o.c (bfd_mach_o_get_synthetic_symtab): Rewrite.
|
||||
---
|
||||
Upstream-Status: Backport from [https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=d12f8998d2d086f0a6606589e5aedb7147e6f2f1]
|
||||
CVE: CVE-2023-25588
|
||||
CVE: CVE-2022-47696
|
||||
|
||||
Signed-off-by: Ashish Sharma <asharma@mvista.com>
|
||||
Signed-off-by: poojitha adireddy <pooadire@cisco.com>
|
||||
|
||||
bfd/mach-o.c | 72 ++++++++++++++++++++++------------------------------
|
||||
1 file changed, 31 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
|
||||
index acb35e7f0c6..5279343768c 100644
|
||||
--- a/bfd/mach-o.c
|
||||
+++ b/bfd/mach-o.c
|
||||
@@ -938,11 +938,9 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
|
||||
bfd_mach_o_symtab_command *symtab = mdata->symtab;
|
||||
asymbol *s;
|
||||
char * s_start;
|
||||
- char * s_end;
|
||||
unsigned long count, i, j, n;
|
||||
size_t size;
|
||||
char *names;
|
||||
- char *nul_name;
|
||||
const char stub [] = "$stub";
|
||||
|
||||
*ret = NULL;
|
||||
@@ -955,27 +953,27 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
|
||||
/* We need to allocate a bfd symbol for every indirect symbol and to
|
||||
allocate the memory for its name. */
|
||||
count = dysymtab->nindirectsyms;
|
||||
- size = count * sizeof (asymbol) + 1;
|
||||
-
|
||||
+ size = 0;
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
- const char * strng;
|
||||
unsigned int isym = dysymtab->indirect_syms[j];
|
||||
+ const char *str;
|
||||
|
||||
/* Some indirect symbols are anonymous. */
|
||||
- if (isym < symtab->nsyms && (strng = symtab->symbols[isym].symbol.name))
|
||||
- /* PR 17512: file: f5b8eeba. */
|
||||
- size += strnlen (strng, symtab->strsize - (strng - symtab->strtab)) + sizeof (stub);
|
||||
+ if (isym < symtab->nsyms
|
||||
+ && (str = symtab->symbols[isym].symbol.name) != NULL)
|
||||
+ {
|
||||
+ /* PR 17512: file: f5b8eeba. */
|
||||
+ size += strnlen (str, symtab->strsize - (str - symtab->strtab));
|
||||
+ size += sizeof (stub);
|
||||
+ }
|
||||
}
|
||||
|
||||
- s_start = bfd_malloc (size);
|
||||
+ s_start = bfd_malloc (size + count * sizeof (asymbol));
|
||||
s = *ret = (asymbol *) s_start;
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
names = (char *) (s + count);
|
||||
- nul_name = names;
|
||||
- *names++ = 0;
|
||||
- s_end = s_start + size;
|
||||
|
||||
n = 0;
|
||||
for (i = 0; i < mdata->nsects; i++)
|
||||
@@ -997,47 +995,39 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd,
|
||||
entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
|
||||
|
||||
/* PR 17512: file: 08e15eec. */
|
||||
- if (first >= count || last >= count || first > last)
|
||||
+ if (first >= count || last > count || first > last)
|
||||
goto fail;
|
||||
|
||||
for (j = first; j < last; j++)
|
||||
{
|
||||
unsigned int isym = dysymtab->indirect_syms[j];
|
||||
-
|
||||
- /* PR 17512: file: 04d64d9b. */
|
||||
- if (((char *) s) + sizeof (* s) > s_end)
|
||||
- goto fail;
|
||||
-
|
||||
- s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
|
||||
- s->section = sec->bfdsection;
|
||||
- s->value = addr - sec->addr;
|
||||
- s->udata.p = NULL;
|
||||
+ const char *str;
|
||||
+ size_t len;
|
||||
|
||||
if (isym < symtab->nsyms
|
||||
- && symtab->symbols[isym].symbol.name)
|
||||
+ && (str = symtab->symbols[isym].symbol.name) != NULL)
|
||||
{
|
||||
- const char *sym = symtab->symbols[isym].symbol.name;
|
||||
- size_t len;
|
||||
-
|
||||
- s->name = names;
|
||||
- len = strlen (sym);
|
||||
- /* PR 17512: file: 47dfd4d2. */
|
||||
- if (names + len >= s_end)
|
||||
+ /* PR 17512: file: 04d64d9b. */
|
||||
+ if (n >= count)
|
||||
goto fail;
|
||||
- memcpy (names, sym, len);
|
||||
- names += len;
|
||||
- /* PR 17512: file: 18f340a4. */
|
||||
- if (names + sizeof (stub) >= s_end)
|
||||
+ len = strnlen (str, symtab->strsize - (str - symtab->strtab));
|
||||
+ /* PR 17512: file: 47dfd4d2, 18f340a4. */
|
||||
+ if (size < len + sizeof (stub))
|
||||
goto fail;
|
||||
- memcpy (names, stub, sizeof (stub));
|
||||
- names += sizeof (stub);
|
||||
+ memcpy (names, str, len);
|
||||
+ memcpy (names + len, stub, sizeof (stub));
|
||||
+ s->name = names;
|
||||
+ names += len + sizeof (stub);
|
||||
+ size -= len + sizeof (stub);
|
||||
+ s->the_bfd = symtab->symbols[isym].symbol.the_bfd;
|
||||
+ s->flags = BSF_GLOBAL | BSF_SYNTHETIC;
|
||||
+ s->section = sec->bfdsection;
|
||||
+ s->value = addr - sec->addr;
|
||||
+ s->udata.p = NULL;
|
||||
+ s++;
|
||||
+ n++;
|
||||
}
|
||||
- else
|
||||
- s->name = nul_name;
|
||||
-
|
||||
addr += entry_size;
|
||||
- s++;
|
||||
- n++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
--
|
||||
2.39.3
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
From 24def311c6168d0dfb7c5f0f183b72b709c49265 Mon Sep 17 00:00:00 2001
|
||||
From: Jean Delvare <jdelvare@suse.de>
|
||||
Date: Mon, 20 Feb 2023 14:53:21 +0100
|
||||
Subject: [PATCH] dmidecode: Split table fetching from decoding
|
||||
|
||||
Clean up function dmi_table so that it does only one thing:
|
||||
* dmi_table() is renamed to dmi_table_get(). It now retrieves the
|
||||
DMI table, but does not process it any longer.
|
||||
* Decoding or dumping the table is now done in smbios3_decode(),
|
||||
smbios_decode() and legacy_decode().
|
||||
No functional change.
|
||||
|
||||
A side effect of this change is that writing the header and body of
|
||||
dump files is now done in a single location. This is required to
|
||||
further consolidate the writing of dump files.
|
||||
|
||||
CVE-ID: CVE-2023-30630
|
||||
Upstream-Status: Backport [https://git.savannah.nongnu.org/cgit/dmidecode.git/commit/?id=39b2dd7b6ab7]
|
||||
|
||||
Backport Changes:
|
||||
- In the file dmidecode.c, the commit [dd593d2] in v3.3 introduces
|
||||
pr_info(). This is backported to printf() as per v3.2.
|
||||
|
||||
Signed-off-by: Jean Delvare <jdelvare@suse.de>
|
||||
Reviewed-by: Jerry Hoemann <jerry.hoemann@hpe.com>
|
||||
(cherry picked from commit 39b2dd7b6ab719b920e96ed832cfb4bdd664e808)
|
||||
Signed-off-by: Dhairya Nagodra <dnagodra@cisco.com>
|
||||
---
|
||||
dmidecode.c | 86 ++++++++++++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 62 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/dmidecode.c b/dmidecode.c
|
||||
index a3e9d6c..d6eedd1 100644
|
||||
--- a/dmidecode.c
|
||||
+++ b/dmidecode.c
|
||||
@@ -5211,8 +5211,9 @@ static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
|
||||
}
|
||||
}
|
||||
|
||||
-static void dmi_table(off_t base, u32 len, u16 num, u32 ver, const char *devmem,
|
||||
- u32 flags)
|
||||
+/* Allocates a buffer for the table, must be freed by the caller */
|
||||
+static u8 *dmi_table_get(off_t base, u32 *len, u16 num, u32 ver,
|
||||
+ const char *devmem, u32 flags)
|
||||
{
|
||||
u8 *buf;
|
||||
|
||||
@@ -5231,7 +5232,7 @@ static void dmi_table(off_t base, u32 len, u16 num, u32 ver, const char *devmem,
|
||||
{
|
||||
if (num)
|
||||
printf("%u structures occupying %u bytes.\n",
|
||||
- num, len);
|
||||
+ num, *len);
|
||||
if (!(opt.flags & FLAG_FROM_DUMP))
|
||||
printf("Table at 0x%08llX.\n",
|
||||
(unsigned long long)base);
|
||||
@@ -5249,19 +5250,19 @@ static void dmi_table(off_t base, u32 len, u16 num, u32 ver, const char *devmem,
|
||||
* would be the result of the kernel truncating the table on
|
||||
* parse error.
|
||||
*/
|
||||
- size_t size = len;
|
||||
+ size_t size = *len;
|
||||
buf = read_file(flags & FLAG_NO_FILE_OFFSET ? 0 : base,
|
||||
&size, devmem);
|
||||
- if (!(opt.flags & FLAG_QUIET) && num && size != (size_t)len)
|
||||
+ if (!(opt.flags & FLAG_QUIET) && num && size != (size_t)*len)
|
||||
{
|
||||
fprintf(stderr, "Wrong DMI structures length: %u bytes "
|
||||
"announced, only %lu bytes available.\n",
|
||||
- len, (unsigned long)size);
|
||||
+ *len, (unsigned long)size);
|
||||
}
|
||||
- len = size;
|
||||
+ *len = size;
|
||||
}
|
||||
else
|
||||
- buf = mem_chunk(base, len, devmem);
|
||||
+ buf = mem_chunk(base, *len, devmem);
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
@@ -5271,15 +5272,9 @@ static void dmi_table(off_t base, u32 len, u16 num, u32 ver, const char *devmem,
|
||||
fprintf(stderr,
|
||||
"Try compiling dmidecode with -DUSE_MMAP.\n");
|
||||
#endif
|
||||
- return;
|
||||
}
|
||||
|
||||
- if (opt.flags & FLAG_DUMP_BIN)
|
||||
- dmi_table_dump(buf, len);
|
||||
- else
|
||||
- dmi_table_decode(buf, len, num, ver >> 8, flags);
|
||||
-
|
||||
- free(buf);
|
||||
+ return buf;
|
||||
}
|
||||
|
||||
|
||||
@@ -5314,8 +5309,9 @@ static void overwrite_smbios3_address(u8 *buf)
|
||||
|
||||
static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
{
|
||||
- u32 ver;
|
||||
+ u32 ver, len;
|
||||
u64 offset;
|
||||
+ u8 *table;
|
||||
|
||||
/* Don't let checksum run beyond the buffer */
|
||||
if (buf[0x06] > 0x20)
|
||||
@@ -5341,8 +5337,12 @@ static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- dmi_table(((off_t)offset.h << 32) | offset.l,
|
||||
- DWORD(buf + 0x0C), 0, ver, devmem, flags | FLAG_STOP_AT_EOT);
|
||||
+ /* Maximum length, may get trimmed */
|
||||
+ len = DWORD(buf + 0x0C);
|
||||
+ table = dmi_table_get(((off_t)offset.h << 32) | offset.l, &len, 0, ver,
|
||||
+ devmem, flags | FLAG_STOP_AT_EOT);
|
||||
+ if (table == NULL)
|
||||
+ return 1;
|
||||
|
||||
if (opt.flags & FLAG_DUMP_BIN)
|
||||
{
|
||||
@@ -5351,18 +5351,28 @@ static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 32);
|
||||
overwrite_smbios3_address(crafted);
|
||||
|
||||
+ dmi_table_dump(table, len);
|
||||
if (!(opt.flags & FLAG_QUIET))
|
||||
printf("# Writing %d bytes to %s.\n", crafted[0x06],
|
||||
opt.dumpfile);
|
||||
write_dump(0, crafted[0x06], crafted, opt.dumpfile, 1);
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ dmi_table_decode(table, len, 0, ver >> 8,
|
||||
+ flags | FLAG_STOP_AT_EOT);
|
||||
+ }
|
||||
+
|
||||
+ free(table);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
{
|
||||
- u16 ver;
|
||||
+ u16 ver, num;
|
||||
+ u32 len;
|
||||
+ u8 *table;
|
||||
|
||||
/* Don't let checksum run beyond the buffer */
|
||||
if (buf[0x05] > 0x20)
|
||||
@@ -5402,8 +5412,13 @@ static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
printf("SMBIOS %u.%u present.\n",
|
||||
ver >> 8, ver & 0xFF);
|
||||
|
||||
- dmi_table(DWORD(buf + 0x18), WORD(buf + 0x16), WORD(buf + 0x1C),
|
||||
- ver << 8, devmem, flags);
|
||||
+ /* Maximum length, may get trimmed */
|
||||
+ len = WORD(buf + 0x16);
|
||||
+ num = WORD(buf + 0x1C);
|
||||
+ table = dmi_table_get(DWORD(buf + 0x18), &len, num, ver << 8,
|
||||
+ devmem, flags);
|
||||
+ if (table == NULL)
|
||||
+ return 1;
|
||||
|
||||
if (opt.flags & FLAG_DUMP_BIN)
|
||||
{
|
||||
@@ -5412,27 +5427,43 @@ static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 32);
|
||||
overwrite_dmi_address(crafted + 0x10);
|
||||
|
||||
+ dmi_table_dump(table, len);
|
||||
if (!(opt.flags & FLAG_QUIET))
|
||||
printf("# Writing %d bytes to %s.\n", crafted[0x05],
|
||||
opt.dumpfile);
|
||||
write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1);
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ dmi_table_decode(table, len, num, ver, flags);
|
||||
+ }
|
||||
+
|
||||
+ free(table);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
{
|
||||
+ u16 ver, num;
|
||||
+ u32 len;
|
||||
+ u8 *table;
|
||||
+
|
||||
if (!checksum(buf, 0x0F))
|
||||
return 0;
|
||||
|
||||
+ ver = ((buf[0x0E] & 0xF0) << 4) + (buf[0x0E] & 0x0F);
|
||||
if (!(opt.flags & FLAG_QUIET))
|
||||
printf("Legacy DMI %u.%u present.\n",
|
||||
buf[0x0E] >> 4, buf[0x0E] & 0x0F);
|
||||
|
||||
- dmi_table(DWORD(buf + 0x08), WORD(buf + 0x06), WORD(buf + 0x0C),
|
||||
- ((buf[0x0E] & 0xF0) << 12) + ((buf[0x0E] & 0x0F) << 8),
|
||||
- devmem, flags);
|
||||
+ /* Maximum length, may get trimmed */
|
||||
+ len = WORD(buf + 0x06);
|
||||
+ num = WORD(buf + 0x0C);
|
||||
+ table = dmi_table_get(DWORD(buf + 0x08), &len, num, ver << 8,
|
||||
+ devmem, flags);
|
||||
+ if (table == NULL)
|
||||
+ return 1;
|
||||
|
||||
if (opt.flags & FLAG_DUMP_BIN)
|
||||
{
|
||||
@@ -5441,11 +5472,18 @@ static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 16);
|
||||
overwrite_dmi_address(crafted);
|
||||
|
||||
+ dmi_table_dump(table, len);
|
||||
if (!(opt.flags & FLAG_QUIET))
|
||||
printf("# Writing %d bytes to %s.\n", 0x0F,
|
||||
opt.dumpfile);
|
||||
write_dump(0, 0x0F, crafted, opt.dumpfile, 1);
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ dmi_table_decode(table, len, num, ver, flags);
|
||||
+ }
|
||||
+
|
||||
+ free(table);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
From 58e8a07b1aef0e53af1642b30248255e53e42790 Mon Sep 17 00:00:00 2001
|
||||
From: Jean Delvare <jdelvare@suse.de>
|
||||
Date: Mon, 20 Feb 2023 14:53:25 +0100
|
||||
Subject: [PATCH] dmidecode: Write the whole dump file at once
|
||||
|
||||
When option --dump-bin is used, write the whole dump file at once,
|
||||
instead of opening and closing the file separately for the table
|
||||
and then for the entry point.
|
||||
|
||||
As the file writing function is no longer generic, it gets moved
|
||||
from util.c to dmidecode.c.
|
||||
|
||||
One minor functional change resulting from the new implementation is
|
||||
that the entry point is written first now, so the messages printed
|
||||
are swapped.
|
||||
|
||||
CVE: CVE-2023-30630
|
||||
Upstream-Status: Backport [https://git.savannah.nongnu.org/cgit/dmidecode.git/commit/?id=d8cfbc808f38]
|
||||
|
||||
Backport Changes:
|
||||
- In the file dmidecode.c, the commit [2241f1d] in v3.3 introduces
|
||||
pr_info(). This is backported to printf() as per v3.2.
|
||||
|
||||
Signed-off-by: Jean Delvare <jdelvare@suse.de>
|
||||
Reviewed-by: Jerry Hoemann <jerry.hoemann@hpe.com>
|
||||
(cherry picked from commit d8cfbc808f387e87091c25e7d5b8c2bb348bb206)
|
||||
Signed-off-by: Dhairya Nagodra <dnagodra@cisco.com>
|
||||
|
||||
---
|
||||
dmidecode.c | 69 +++++++++++++++++++++++++++++++++++++++--------------
|
||||
util.c | 40 -------------------------------
|
||||
util.h | 1 -
|
||||
3 files changed, 51 insertions(+), 59 deletions(-)
|
||||
|
||||
diff --git a/dmidecode.c b/dmidecode.c
|
||||
index d6eedd1..b91e53b 100644
|
||||
--- a/dmidecode.c
|
||||
+++ b/dmidecode.c
|
||||
@@ -5094,11 +5094,56 @@ static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver
|
||||
}
|
||||
}
|
||||
|
||||
-static void dmi_table_dump(const u8 *buf, u32 len)
|
||||
+static int dmi_table_dump(const u8 *ep, u32 ep_len, const u8 *table,
|
||||
+ u32 table_len)
|
||||
{
|
||||
+ FILE *f;
|
||||
+
|
||||
+ f = fopen(opt.dumpfile, "wb");
|
||||
+ if (!f)
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("fopen");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (!(opt.flags & FLAG_QUIET))
|
||||
+ printf("# Writing %d bytes to %s.\n", ep_len, opt.dumpfile);
|
||||
+ if (fwrite(ep, ep_len, 1, f) != 1)
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("fwrite");
|
||||
+ goto err_close;
|
||||
+ }
|
||||
+
|
||||
+ if (fseek(f, 32, SEEK_SET) != 0)
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("fseek");
|
||||
+ goto err_close;
|
||||
+ }
|
||||
+
|
||||
if (!(opt.flags & FLAG_QUIET))
|
||||
- printf("# Writing %d bytes to %s.\n", len, opt.dumpfile);
|
||||
- write_dump(32, len, buf, opt.dumpfile, 0);
|
||||
+ printf("# Writing %d bytes to %s.\n", table_len, opt.dumpfile);
|
||||
+ if (fwrite(table, table_len, 1, f) != 1)
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("fwrite");
|
||||
+ goto err_close;
|
||||
+ }
|
||||
+
|
||||
+ if (fclose(f))
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("fclose");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_close:
|
||||
+ fclose(f);
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
static void dmi_table_decode(u8 *buf, u32 len, u16 num, u16 ver, u32 flags)
|
||||
@@ -5351,11 +5396,7 @@ static int smbios3_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 32);
|
||||
overwrite_smbios3_address(crafted);
|
||||
|
||||
- dmi_table_dump(table, len);
|
||||
- if (!(opt.flags & FLAG_QUIET))
|
||||
- printf("# Writing %d bytes to %s.\n", crafted[0x06],
|
||||
- opt.dumpfile);
|
||||
- write_dump(0, crafted[0x06], crafted, opt.dumpfile, 1);
|
||||
+ dmi_table_dump(crafted, crafted[0x06], table, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5427,11 +5468,7 @@ static int smbios_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 32);
|
||||
overwrite_dmi_address(crafted + 0x10);
|
||||
|
||||
- dmi_table_dump(table, len);
|
||||
- if (!(opt.flags & FLAG_QUIET))
|
||||
- printf("# Writing %d bytes to %s.\n", crafted[0x05],
|
||||
- opt.dumpfile);
|
||||
- write_dump(0, crafted[0x05], crafted, opt.dumpfile, 1);
|
||||
+ dmi_table_dump(crafted, crafted[0x05], table, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5472,11 +5509,7 @@ static int legacy_decode(u8 *buf, const char *devmem, u32 flags)
|
||||
memcpy(crafted, buf, 16);
|
||||
overwrite_dmi_address(crafted);
|
||||
|
||||
- dmi_table_dump(table, len);
|
||||
- if (!(opt.flags & FLAG_QUIET))
|
||||
- printf("# Writing %d bytes to %s.\n", 0x0F,
|
||||
- opt.dumpfile);
|
||||
- write_dump(0, 0x0F, crafted, opt.dumpfile, 1);
|
||||
+ dmi_table_dump(crafted, 0x0F, table, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/util.c b/util.c
|
||||
index eeffdae..2e1931c 100644
|
||||
--- a/util.c
|
||||
+++ b/util.c
|
||||
@@ -247,46 +247,6 @@ out:
|
||||
return p;
|
||||
}
|
||||
|
||||
-int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add)
|
||||
-{
|
||||
- FILE *f;
|
||||
-
|
||||
- f = fopen(dumpfile, add ? "r+b" : "wb");
|
||||
- if (!f)
|
||||
- {
|
||||
- fprintf(stderr, "%s: ", dumpfile);
|
||||
- perror("fopen");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- if (fseek(f, base, SEEK_SET) != 0)
|
||||
- {
|
||||
- fprintf(stderr, "%s: ", dumpfile);
|
||||
- perror("fseek");
|
||||
- goto err_close;
|
||||
- }
|
||||
-
|
||||
- if (fwrite(data, len, 1, f) != 1)
|
||||
- {
|
||||
- fprintf(stderr, "%s: ", dumpfile);
|
||||
- perror("fwrite");
|
||||
- goto err_close;
|
||||
- }
|
||||
-
|
||||
- if (fclose(f))
|
||||
- {
|
||||
- fprintf(stderr, "%s: ", dumpfile);
|
||||
- perror("fclose");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-err_close:
|
||||
- fclose(f);
|
||||
- return -1;
|
||||
-}
|
||||
-
|
||||
/* Returns end - start + 1, assuming start < end */
|
||||
u64 u64_range(u64 start, u64 end)
|
||||
{
|
||||
diff --git a/util.h b/util.h
|
||||
index 3094cf8..ef24eb9 100644
|
||||
--- a/util.h
|
||||
+++ b/util.h
|
||||
@@ -27,5 +27,4 @@
|
||||
int checksum(const u8 *buf, size_t len);
|
||||
void *read_file(off_t base, size_t *len, const char *filename);
|
||||
void *mem_chunk(off_t base, size_t len, const char *devmem);
|
||||
-int write_dump(size_t base, size_t len, const void *data, const char *dumpfile, int add);
|
||||
u64 u64_range(u64 start, u64 end);
|
||||
@@ -0,0 +1,62 @@
|
||||
From b7dacccff32294ea522df32a9391d0218e7600ea Mon Sep 17 00:00:00 2001
|
||||
From: Jean Delvare <jdelvare@suse.de>
|
||||
Date: Mon, 20 Feb 2023 14:53:31 +0100
|
||||
Subject: [PATCH] dmidecode: Do not let --dump-bin overwrite an existing file
|
||||
|
||||
Make sure that the file passed to option --dump-bin does not already
|
||||
exist. In practice, it is rather unlikely that an honest user would
|
||||
want to overwrite an existing dump file, while this possibility
|
||||
could be used by a rogue user to corrupt a system file.
|
||||
|
||||
CVE: CVE-2023-30630
|
||||
Upstream-Status: Backport [https://git.savannah.nongnu.org/cgit/dmidecode.git/commit/?id=6ca381c1247c]
|
||||
|
||||
Backport Changes:
|
||||
- Ignored changes in man/dmidecode.8 file.
|
||||
|
||||
Signed-off-by: Jean Delvare <jdelvare@suse.de>
|
||||
Reviewed-by: Jerry Hoemann <jerry.hoemann@hpe.com>
|
||||
(cherry picked from commit 6ca381c1247c81f74e1ca4e7706f70bdda72e6f2)
|
||||
Signed-off-by: Dhairya Nagodra <dnagodra@cisco.com>
|
||||
|
||||
---
|
||||
dmidecode.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dmidecode.c b/dmidecode.c
|
||||
index b91e53b..846d9a1 100644
|
||||
--- a/dmidecode.c
|
||||
+++ b/dmidecode.c
|
||||
@@ -60,6 +60,7 @@
|
||||
* https://www.dmtf.org/sites/default/files/DSP0270_1.0.1.pdf
|
||||
*/
|
||||
|
||||
+#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
@@ -5097,13 +5098,22 @@ static void dmi_table_string(const struct dmi_header *h, const u8 *data, u16 ver
|
||||
static int dmi_table_dump(const u8 *ep, u32 ep_len, const u8 *table,
|
||||
u32 table_len)
|
||||
{
|
||||
+ int fd;
|
||||
FILE *f;
|
||||
|
||||
- f = fopen(opt.dumpfile, "wb");
|
||||
+ fd = open(opt.dumpfile, O_WRONLY|O_CREAT|O_EXCL, 0666);
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
+ perror("open");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ f = fdopen(fd, "wb");
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "%s: ", opt.dumpfile);
|
||||
- perror("fopen");
|
||||
+ perror("fdopen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
|
||||
|
||||
SRC_URI = "${SAVANNAH_NONGNU_MIRROR}/dmidecode/${BP}.tar.xz \
|
||||
file://0001-Committing-changes-from-do_unpack_extra.patch \
|
||||
file://CVE-2023-30630-dependent_p1.patch \
|
||||
file://CVE-2023-30630-dependent_p2.patch \
|
||||
file://CVE-2023-30630.patch \
|
||||
"
|
||||
|
||||
COMPATIBLE_HOST = "(i.86|x86_64|aarch64|arm|powerpc|powerpc64).*-linux"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user