sys-libs/libseccomp: fix aliasing violation

The patch isn't perfect so may revbump with a tweaked version later.

Signed-off-by: Sam James <sam@gentoo.org>
This commit is contained in:
Sam James
2025-03-10 00:14:15 +00:00
parent 2bef63ab1f
commit 1b1023ec6b
2 changed files with 177 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
https://github.com/seccomp/libseccomp/pull/459
From e6904da422e68031b0237c1e005fc5e98c12e2cf Mon Sep 17 00:00:00 2001
From: Romain Geissler <romain.geissler@amadeus.com>
Date: Tue, 18 Feb 2025 22:29:05 +0000
Subject: [PATCH] Fix strict aliasing UB in MurMur hash implementation.
This was spotted when trying to upgrade the libseccomp fedora package to
version 2.6.0 in fedora rawhide. It comes with gcc 15 and LTO enabled by
default. When running the test 61-sim-transactions we get plenty of such
errors in valgrind:
==265507== Use of uninitialised value of size 8
==265507== at 0x4096AD: _hsh_add (gen_bpf.c:599)
==265507== by 0x40A557: UnknownInlinedFun (gen_bpf.c:2016)
==265507== by 0x40A557: gen_bpf_generate (gen_bpf.c:2341)
==265507== by 0x400CDE: UnknownInlinedFun (db.c:2685)
==265507== by 0x400CDE: UnknownInlinedFun (db.c:2682)
==265507== by 0x400CDE: UnknownInlinedFun (api.c:756)
==265507== by 0x400CDE: UnknownInlinedFun (util.c:162)
==265507== by 0x400CDE: UnknownInlinedFun (util.c:153)
==265507== by 0x400CDE: main (61-sim-transactions.c:128)
==265507== Uninitialised value was created by a stack allocation
==265507== at 0x409590: _hsh_add (gen_bpf.c:573)
Investigating this a bit, it seems that because of LTO the MurMur hash
implementation is being inlined in _hsh_add. The way we call getblock32
with the explicit cast to const uint32_t* is a strict aliasing
violation.
This is reproducible on a "fedora:rawhide" container (gcc 15) and using:
export CFLAGS='-O2 -flto=auto -ffat-lto-objects -g'
Signed-off-by: Romain Geissler <romain.geissler@amadeus.com>
---
src/hash.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/hash.c b/src/hash.c
index 4435900f..301abfc9 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -12,15 +12,11 @@
*/
#include <stdlib.h>
+#include <string.h>
#include <inttypes.h>
#include "hash.h"
-static inline uint32_t getblock32(const uint32_t *p, int i)
-{
- return p[i];
-}
-
static inline uint32_t rotl32(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
@@ -56,7 +52,7 @@ uint32_t hash(const void *key, size_t length)
/* body */
blocks = (const uint32_t *)(data + nblocks * 4);
for(i = -nblocks; i; i++) {
- k1 = getblock32(blocks, i);
+ memcpy(&k1, &blocks[i], sizeof(uint32_t));
k1 *= c1;
k1 = rotl32(k1, 15);

View File

@@ -0,0 +1,108 @@
# Copyright 1999-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI=8
DISTUTILS_EXT=1
DISTUTILS_OPTIONAL=1
DISTUTILS_USE_PEP517=setuptools
PYTHON_COMPAT=( python3_{10..13} )
inherit distutils-r1 multilib-minimal
DESCRIPTION="High level interface to Linux seccomp filter"
HOMEPAGE="https://github.com/seccomp/libseccomp"
if [[ ${PV} == *9999 ]] ; then
EGIT_REPO_URI="https://github.com/seccomp/libseccomp.git"
PRERELEASE="2.6.0"
inherit autotools git-r3
else
SRC_URI="https://github.com/seccomp/libseccomp/releases/download/v${PV}/${P}.tar.gz"
KEYWORDS="-* ~amd64 ~arm ~arm64 ~hppa ~loong ~mips ~ppc ~ppc64 ~riscv ~s390 ~x86 ~amd64-linux ~x86-linux"
fi
LICENSE="LGPL-2.1"
SLOT="0"
IUSE="python static-libs test"
RESTRICT="!test? ( test )"
REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
# We need newer kernel headers; we don't keep strict control of the exact
# version here, just be safe and pull in the latest stable ones. bug #551248
DEPEND="
>=sys-kernel/linux-headers-5.15
python? ( ${PYTHON_DEPS} )
"
RDEPEND="${DEPEND}"
BDEPEND="
${DEPEND}
dev-util/gperf
python? (
${DISTUTILS_DEPS}
dev-python/cython[${PYTHON_USEDEP}]
)
"
PATCHES=(
"${FILESDIR}"/libseccomp-2.6.0-python-shared.patch
"${FILESDIR}"/libseccomp-2.5.3-skip-valgrind.patch
"${FILESDIR}"/${P}-drop-bogus-test.patch
"${FILESDIR}"/${PN}-2.6.0-aliasing.patch
)
src_prepare() {
default
if [[ ${PV} == *9999 ]] ; then
sed -i -e "s/0.0.0/${PRERELEASE}/" configure.ac || die
eautoreconf
fi
}
multilib_src_configure() {
local myeconfargs=(
$(use_enable static-libs static)
--disable-python
)
ECONF_SOURCE="${S}" econf "${myeconfargs[@]}"
}
multilib_src_compile() {
emake
if multilib_is_native_abi && use python ; then
# setup.py expects libseccomp.so to live in "../.libs"
# Copy the python files to the right place for this.
rm -r "${BUILD_DIR}"/src/python || die
cp -r "${S}"/src/python "${BUILD_DIR}"/src/python || die
local -x CPPFLAGS="-I\"${BUILD_DIR}/include\" -I\"${S}/include\" ${CPPFLAGS}"
# setup.py reads VERSION_RELEASE from the environment
local -x VERSION_RELEASE=${PRERELEASE-${PV}}
pushd "${BUILD_DIR}/src/python" >/dev/null || die
distutils-r1_src_compile
popd >/dev/null || die
fi
}
multilib_src_test() {
emake -Onone check
}
multilib_src_install() {
emake DESTDIR="${D}" install
if multilib_is_native_abi && use python ; then
distutils-r1_src_install
fi
}
multilib_src_install_all() {
find "${ED}" -type f -name "${PN}.la" -delete || die
einstalldocs
}