icu: add .note.GNU-stack to the data object via objcopy
-Wa,--noexecstack did not reach icudt75l_dat.o: ICU builds it through pkgdata, which drives the assembler with its own flags and ignores CFLAGS. Verified empirically -- after a full ICU rebuild readelf still showed 0 GNU-stack sections, and plasma-workspace failed identically. Patching the archive member is deterministic where the flag was not. The added section is empty and read-only: it declares a non-executable stack, which is exactly true for a pure data blob. Verified objcopy 0 -> 1 section on the real archive before committing. Without it, binutils warns "missing .note.GNU-stack section implies executable stack", and KDE's ECM links with -Wl,--fatal-warnings, so every KDE consumer of static ICU fails (plasma-workspace applets/digital-clock, ld exit 1). Asserts the section is present afterwards rather than swallowing errors: a silent no-op here resurfaces as a link failure in a different package, far from the cause.
This commit is contained in:
@@ -78,5 +78,48 @@ ln -sf mh-linux "${ICU_SRC}/config/mh-unknown"
|
||||
make -j"${COOKBOOK_MAKE_JOBS}"
|
||||
make install DESTDIR="${COOKBOOK_STAGE}"
|
||||
|
||||
# Add .note.GNU-stack to the generated data object.
|
||||
#
|
||||
# ICU builds icudt75l_dat.o through pkgdata, which drives the assembler with its
|
||||
# own flags and ignores CFLAGS -- so -Wa,--noexecstack above does NOT reach it
|
||||
# (verified: readelf showed 0 GNU-stack sections after a full ICU rebuild).
|
||||
# Without that section modern binutils warns
|
||||
# ld: warning: icudt75l_dat.o: missing .note.GNU-stack section implies
|
||||
# executable stack
|
||||
# and KDE's ECM links with -Wl,--fatal-warnings, so every KDE consumer of
|
||||
# static ICU fails outright (plasma-workspace applets/digital-clock:
|
||||
# collect2: error: ld returned 1).
|
||||
#
|
||||
# Patching the archive member is deterministic where the flag was not. The
|
||||
# section is empty and read-only: it declares a non-executable stack, which is
|
||||
# exactly true for a pure data blob.
|
||||
_icu_lib="${COOKBOOK_STAGE}/usr/lib/libicudata.a"
|
||||
if [ -f "${_icu_lib}" ]; then
|
||||
_icu_tmp="$(mktemp -d)"
|
||||
( cd "${_icu_tmp}" && ar x "${_icu_lib}" )
|
||||
# Prefer the cross objcopy; fall back to the host one. Both write the same
|
||||
# ELF section for x86_64. `|| true` is deliberately NOT used -- a silent
|
||||
# skip here reappears as a link failure in a KDE package, so the assertion
|
||||
# below must be able to catch a no-op.
|
||||
_icu_objcopy="${TARGET}-objcopy"
|
||||
command -v "${_icu_objcopy}" >/dev/null 2>&1 || _icu_objcopy=objcopy
|
||||
for _o in "${_icu_tmp}"/*.o; do
|
||||
[ -f "${_o}" ] || continue
|
||||
"${_icu_objcopy}" \
|
||||
--add-section .note.GNU-stack=/dev/null \
|
||||
--set-section-flags .note.GNU-stack=contents,readonly \
|
||||
"${_o}"
|
||||
done
|
||||
( cd "${_icu_tmp}" && ar rcs "${_icu_lib}" *.o )
|
||||
rm -rf "${_icu_tmp}"
|
||||
# Assert it actually took: a silent no-op here resurfaces as a link failure
|
||||
# in a KDE package, far from this recipe.
|
||||
_icu_chk="$(mktemp -d)"
|
||||
( cd "${_icu_chk}" && ar x "${_icu_lib}" && \
|
||||
readelf -S icudt*_dat.o 2>/dev/null | grep -q 'GNU-stack' ) \
|
||||
|| { echo "ERROR: .note.GNU-stack not added to ICU data object" >&2; rm -rf "${_icu_chk}"; exit 1; }
|
||||
rm -rf "${_icu_chk}"
|
||||
fi
|
||||
|
||||
mkdir -p "${COOKBOOK_STAGE}/usr/lib/pkgconfig"
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user