diff mbox series

package/qt5webengine: fix no executable stack link issue on arm

Message ID 20240731110813.17489-1-gael.portay@rtone.fr
State New
Headers show
Series package/qt5webengine: fix no executable stack link issue on arm | expand

Commit Message

Gaël PORTAY July 31, 2024, 11:08 a.m. UTC
TL;DR; This turns the configure flag -no-feature-webengine-noexecstack
to -feature-webengine-noexecstack to workaround a link issue on ARM
32-bit if chromium requests for an executable stack.

And now, the long story...

The configure flag -no-feature-webengine-noexecstack was introduced with
commit 675cbaf9aa (package/qt5/qt5webengine: bump to version 5.15.8).

That configure flag controls the feature webengine-noexecstack[1][2];
the -no-feature-webengine-noexecstack causes qmake to **NOT** append the
linker flags -Wl,-z,noexecstack[3] to QMAKE_LFLAGS.

It results in the linkage issue below on ARM 32-bit at the creation of
its Qt module, i.e. after qmake has built the chromium third party via
gn:

	ulimit -n 4096 && /home/gportay/src/buildroot/output/host/bin/arm-buildroot-linux-gnueabihf-g++ --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_o.rsp -Wl,--start-group @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_a.rsp -Wl,--end-group -Wl,--fatal-warnings -Wl,--build-id=sha1 -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,defs -Wl,-O2 -Wl,--gc-sections --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot -Wl,-O1 -Wl,--enable-new-dtags -Wl,-whole-archive -lqtwebenginecoreapi -Wl,-no-whole-archive -Wl,--no-undefined -Wl,--version-script,QtWebEngineCore.version -Wl,-O1 -Wl,--enable-new-dtags -shared -Wl,-soname,libQt5WebEngineCore.so.5 -o libQt5WebEngineCore.so.5.15.14   -latomic /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Quick.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Gui.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5QmlModels.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5WebChannel.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Qml.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Network.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Core.so -lpthread -L/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib -latomic -lGLESv2 -lpthread -ldl -lrt -lnss3 -lnssutil3 -lsmime3 -lplds4 -lplc4 -lnspr4 -levent -lresolv -ljpeg -lopus -lm -lz -lvpx -lpng16 -lwebp -lwebpmux -lwebpdemux -lfreetype -lexpat -lfontconfig -lharfbuzz-subset -lharfbuzz -lsnappy -lxml2 -lxslt -ldbus-1 -L/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/api/release -lGLESv2 -lrt -lpthread -ldl
	/home/gportay/src/buildroot/output/host/lib/gcc/arm-buildroot-linux-gnueabihf/13.3.0/../../../../arm-buildroot-linux-gnueabihf/bin/ld: warning: /home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o: missing .note.GNU-stack section implies executable stack
	/home/gportay/src/buildroot/output/host/lib/gcc/arm-buildroot-linux-gnueabihf/13.3.0/../../../../arm-buildroot-linux-gnueabihf/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
	collect2: error: ld returned 1 exit status

The link succeeds if the missing linker flags are appended manually to
the command-line:

	ulimit -n 4096 && /home/gportay/src/buildroot/output/host/bin/arm-buildroot-linux-gnueabihf-g++ --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_o.rsp -Wl,--start-group @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_a.rsp -Wl,--end-group -Wl,--fatal-warnings -Wl,--build-id=sha1 -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,defs -Wl,-O2 -Wl,--gc-sections --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot -Wl,-O1 -Wl,--enable-new-dtags -Wl,-whole-archive -lqtwebenginecoreapi -Wl,-no-whole-archive -Wl,--no-undefined -Wl,--version-script,QtWebEngineCore.version -Wl,-O1 -Wl,--enable-new-dtags -shared -Wl,-soname,libQt5WebEngineCore.so.5 -o libQt5WebEngineCore.so.5.15.14   -latomic /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Quick.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Gui.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5QmlModels.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5WebChannel.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Qml.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Network.so /home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/libQt5Core.so -lpthread -L/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib -latomic -lGLESv2 -lpthread -ldl -lrt -lnss3 -lnssutil3 -lsmime3 -lplds4 -lplc4 -lnspr4 -levent -lresolv -ljpeg -lopus -lvpx -lm -lpng16 -lwebp -lwebpmux -lwebpdemux -lfreetype -lexpat -lfontconfig -lharfbuzz-subset -lharfbuzz -lsnappy -lxml2 -lxslt -ldbus-1 -L/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/api/release -lGLESv2 -lrt -lpthread -ldl -Wl,-z,noexecstack && echo completed
	completed

Note: The configure flag is not forwarded to chromium in any manner; its
scope is limited to the Qt WebEngine module. That configure flag appears
to be a workaround if the does not assemble, compile and link the Elf
object correctly[4][5].

The linker flag -z noexecstack is responsible for marking the object as
not requiring an executable stack by adding the section .note.GNU-stack
in the Elf object.

The file SaveRegisters_arm.S is assembled from the command-line below;
there is no noexecstack flag set:

	/home/gportay/src/buildroot/output/host/bin/arm-buildroot-linux-gnueabihf-gcc -MMD -MF obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o.d -DARM=1 -DUSE_UDEV -DUSE_AURA=1 -DUSE_NSS_CERTS=1 -DUSE_OZONE=1 -DOFFICIAL_BUILD -DTOOLKIT_QT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNO_UNWIND_TABLES -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DCR_SYSROOT_HASH=c2e54f675b83a61301dcdb22e8e7a2b85c01d58c -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -Igen -I../../3rdparty/chromium -fPIC -fno-strict-aliasing --param=ssp-buffer-size=4 -fstack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fPIC -pipe -pthread -std=gnu11 -march=armv7-a -mfloat-abi=hard -mtune=generic-armv7-a -mfpu=vfpv3-d16 -marm -g0 --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot -c ../../3rdparty/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm.S -o obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o

The GNU assembler supports the assembler flag -Wa,--{,no}execstack to
require, or not, an executable stack for the object to assemble.

The BUILD.gn does **NOT** set it for the assembler files of the blink
third-party; but it does it for boringssl[6] (see also the project file
CMakeLists.txt[7]).

See below what readelf says if the file is assembled manually with the
flag --noexecstack:

	$ /home/gportay/src/buildroot/output/host/bin/arm-buildroot-linux-gnueabihf-gcc -MMD -MF obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o.d -DARM=1 -DUSE_UDEV -DUSE_AURA=1 -DUSE_NSS_CERTS=1 -DUSE_OZONE=1 -DOFFICIAL_BUILD -DTOOLKIT_QT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -DNO_UNWIND_TABLES -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -DCR_SYSROOT_HASH=c2e54f675b83a61301dcdb22e8e7a2b85c01d58c -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -Igen -I../../3rdparty/chromium -fPIC -fno-strict-aliasing --param=ssp-buffer-size=4 -fstack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fPIC -pipe -pthread -std=gnu11 -march=armv7-a -mfloat-abi=hard -mtune=generic-armv7-a -mfpu=vfpv3-d16 -marm -g0 --sysroot=/home/gportay/src/buildroot/output/host/arm-buildroot-linux-gnueabihf/sysroot -c ../../3rdparty/chromium/third_party/blink/renderer/platform/heap/asm/SaveRegisters_arm.S -o obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o -Wa,--noexecstack

	$ readelf -a /home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/obj/third_party/blink/renderer/platform/heap/asm/asm/SaveRegisters_arm.o
	(...)
	Section Headers:
	  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
	  (...)
	  [ 4] .note.GNU-stack   PROGBITS        00000000 000058 000000 00      0   0  1

The section the linker claims for is now part of the Elf object; and
qmake is now able to link its Qt WebEngine module.

Note: Alternatively, the patching the file SaveRegisters_arm.S to set
explicitly the section in the source file works as well (this reduces
the impact to the very single file causing the link issue):

	#if defined(__linux__) && defined(__ELF__)
	.section .note.GNU-stack,"",%progbits
	#endif

Instead of fixing directly the origin of the issue and setting the
missing assembler flag -Wa,--noexecstack to blink; this works around the
link issue by turning on the feature noexecstack to qtwebengine to force
qmake to link its module using the linker flag -Wl,-z,noexecstack.

[1]: https://github.com/qt/qtwebengine/blob/5.15.14/src/buildtools/configure.json#L353-L357
[2]: https://github.com/qt/qtwebengine/blob/5.15.14/src/buildtools/configure.json#L720-L724
[3]: https://github.com/qt/qtwebengine/blob/5.15.14/src/buildtools/config/linking.pri#L61-L62
[4]: https://github.com/qt/qtwebengine/commit/597359a16a798df3955404200f1fc6833a7425ab
[5]: https://codereview.qt-project.org/c/qt/qtwebengine/+/263545
[6]: https://github.com/qt/qtwebengine-chromium/blob/87-based/chromium/third_party/boringssl/src/util/BUILD.toplevel#L64
[7]: https://github.com/qt/qtwebengine-chromium/blob/87-based/chromium/third_party/boringssl/src/crypto/CMakeLists.txt#L33

Signed-off-by: Gaël PORTAY <gael.portay@rtone.fr>
---
Hello maintainers,

I request you help on that one, as I am not an expert in qmake/gn.

I am fixing the raspberrypi3_qt5we_defconfig that fails to link the Qt
WebEngine because a file in the chromium source is missing the section
.note.GNU-stack.

Note: Disable the BR2_PACKAGE_QT5WEBENGINE_PROPRIETARY_CODECS that
builds VP8 from the bundle ffmpeg third-party (with Chrome flavour,
instead of Chromium) and raises an assembler issue; the fix is ongoing.

I came to the conclusion the flag -webengine-feature-noexecstack from
qtwebengine is a workaround for the qmake if the chromium build system
has bugs against the nostackstack.

I see three solutions:
 1. that one to force qmake to use the -Wl,-z,noexecstack to workaround
    the link issue
 2. patching the assembler file manually to add the missing section and
    workaround the assembling issue
 3. patching the gn file to add the missing assembler flag
    -Wa,--nostackexec and fix the assembling issue

The 3. is the correct solution in my option and I am not skilled enough
in gn to patch the BUILD.gn of blink.

The 2. has the advantage of limited the fix to the very single culprit;
but the fix has to be ported to other architectures if needed (arm64
works but I have not tested it on MIPS, x86...).

The 1. is the most simple and non-invasive considering the change of the
sources; it can be considered to limit it to BR2_arm only to limit the
impact on the other architectures.

It is important to take in consideration these assembler files are gone
since chromium 94; and I wonder the qtwebengine will consider bumping
chromium to a more recent version.

Note: The LLVM assembler does not support for these --{,no}execstack
flags.

Also: The linker does not complain on ARM 64-bit, at least for now; here
is the link command that succeeds even if -Wl,-z,noexecstack; I miss the
command-line assembling the SaveRegisters_arm64.S and the output for the
resulting Elf object file.

	ulimit -n 4096 && /home/gportay/src/buildroot/output/host/bin/aarch64-buildroot-linux-gnu-g++ --sysroot=/home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_o.rsp -Wl,--start-group @/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/release/QtWebEngineCore_a.rsp -Wl,--end-group -Wl,--fatal-warnings -Wl,--build-id=sha1 -fPIC -Wl,-z,relro -Wl,-z,now -Wl,-z,defs -Wl,-O2 -Wl,--gc-sections --sysroot=/home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot --sysroot=/home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot -Wl,-O1 -Wl,--enable-new-dtags -Wl,-whole-archive -lqtwebenginecoreapi -Wl,-no-whole-archive -Wl,--no-undefined -Wl,--version-script,QtWebEngineCore.version -Wl,-O1 -Wl,--enable-new-dtags -shared -Wl,-soname,libQt5WebEngineCore.so.5 -o libQt5WebEngineCore.so.5.15.14   -latomic /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5Quick.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5Gui.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5QmlModels.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5WebChannel.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5Qml.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5Network.so /home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib/libQt5Core.so -lpthread -L/home/gportay/src/buildroot/output/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib -latomic -lGLESv2 -lpthread -ldl -lrt -lnss3 -lnssutil3 -lsmime3 -lplds4 -lplc4 -lnspr4 -levent -lresolv -ljpeg -lm -lopus -lz -lvpx -lpng16 -lwebp -lwebpmux -lwebpdemux -lfreetype -lexpat -lfontconfig -lharfbuzz-subset -lharfbuzz -lsnappy -lxml2 -lxslt -ldbus-1 -L/home/gportay/src/buildroot/output/build/qt5webengine-5.15.14/src/core/api/release -lGLESv2 -lrt -lpthread -ldl

My apologize for that long commit message, it may be messy and not very
well orginized. There is too many information in there and it will be
shorten in the next version depending the review.

Kind Regards,
Gaël
---
 package/qt5/qt5webengine/qt5webengine.mk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/package/qt5/qt5webengine/qt5webengine.mk b/package/qt5/qt5webengine/qt5webengine.mk
index 529a83df6c..a97d918cfd 100644
--- a/package/qt5/qt5webengine/qt5webengine.mk
+++ b/package/qt5/qt5webengine/qt5webengine.mk
@@ -88,6 +88,7 @@  QT5WEBENGINE_CONF_OPTS += \
 	-webengine-webp \
 	-feature-build-qtwebengine-core \
 	-feature-webengine-core-support \
+	-feature-webengine-noexecstack \
 	-feature-webengine-system-dbus \
 	-feature-webengine-system-fontconfig \
 	-feature-webengine-system-freetype \
@@ -117,7 +118,6 @@  QT5WEBENGINE_CONF_OPTS += \
 	-no-feature-webengine-developer-build \
 	-no-feature-webengine-full-debug-info \
 	-no-feature-webengine-native-spellchecker \
-	-no-feature-webengine-noexecstack \
 	-no-feature-webengine-system-minizip \
 	-no-feature-webengine-system-gn