Bug 2350935 - When compiling Python with systemtap support, the branch protections on aarch64 do not get applied
Summary: When compiling Python with systemtap support, the branch protections on aarch...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: python3.14
Version: rawhide
Hardware: aarch64
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Charalampos Stratakis
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2025-03-09 04:26 UTC by Charalampos Stratakis
Modified: 2025-04-23 12:13 UTC (History)
9 users (show)

Fixed In Version: python3.14-3.14.0~a7-1.fc40, python3.14-3.14.0~a7-1.fc41, python3.14-3.14.0~a7-1.fc42, python3.14-3.14.0~a7-1.fc43
Clone Of:
Environment:
Last Closed: 2025-04-23 12:13:14 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Github python cpython issues 131865 0 None closed Systemtap on linux does not properly apply hardening CFLAGS when compiling using --with-dtrace 2025-03-31 20:08:57 UTC

Description Charalampos Stratakis 2025-03-09 04:26:32 UTC
When compiling Python with the --with-dtrace configure flag during RPM build on aarch64 with the -mbranch-protection=standard flag, for applying the Branch Target Identification(BTI) protections, the resulting object file (pydtrace.o) doesn't contain the protections and the associated elf note, resulting in the final shared library missing the note.

Using python3.11, as later versions contain assembly sources that interfere with the results.

Everything looks good when compiling on a non-rpmbuild environment:

./configure --with-dtrace && make -j

$ readelf -n libpython3.11.so.1.0
  Properties: AArch64 feature: BTI, PAC, GCS

$ objdump -d Python/pydtrace.o
  0000000000000000 <__dtrace>:
   0:	d503245f 	bti	c
   4:	d503201f 	nop
   8:	d65f03c0 	ret

However when building Python as an RPM the aarch64 protection flags are not there for libpython or pydtrace.o

$ objdump -d Python/pydtrace.o
0000000000000000 <__dtrace>:
   0:   d503201f        nop
   4:   d65f03c0        ret

I wasn't able to replicate the results by simulating the rpm build on the upstream sources, aka using all our configure options and CFLAGS.

The commands from the Makefile that initiate this:
/usr/bin/dtrace  -o Include/pydtrace_probes.h -h -s /builddir/build/BUILD/python3.11-3.11.11-build/Python-3.11.11/Include/pydtrace.d

sed 's/PYTHON_/PyDTrace_/' Include/pydtrace_probes.h > Include/pydtrace_probes.h.tmp

mv Include/pydtrace_probes.h.tmp Include/pydtrace_probes.h

/usr/bin/dtrace  -o Python/pydtrace.o -G -s /builddir/build/BUILD/python3.11-3.11.11-build/Python-3.11.11/Include/pydtrace.d Python/ceval.o Python/import.o Python/sysmodule.o Modules/gcmodule.o

At the same time the equivalent protection for x86_64 get applied properly for both rpm and non-rpm builds.

Filing for systemtap for now if folks have any insight on that.

Reproducible: Always

Comment 1 Charalampos Stratakis 2025-03-09 14:37:15 UTC
Python/ceval.o Python/import.o Python/sysmodule.o and Modules/gcmodule.o all contain the note in the rpm build.

Comment 2 Charalampos Stratakis 2025-03-09 14:46:11 UTC
Also building the rpm in mock on an aarch64 machine and then from the BUILD directory rerunning manually:

/usr/bin/dtrace  -o Python/pydtrace.o -G -s /builddir/build/BUILD/python3.11-3.11.11-build/Python-3.11.11/Include/pydtrace.d Python/ceval.o Python/import.o Python/sysmodule.o Modules/gcmodule.o

The results are the same, there is no "bti c" or the note in pydtrace.o

Comment 3 Charalampos Stratakis 2025-03-09 16:15:24 UTC
Building the upstream sources within a mock environment in an aarch64 machine didn't reproduce the issue so the problem is not mock itself.

Comment 4 Frank Ch. Eigler 2025-03-10 16:36:52 UTC
The /usr/bin/dtrace script doesn't have a command line option to pass along extra hardening cflags.  However, it observes the $CLFAGS environment variable and relays those to the inferior gcc.  (This is an accidentally undocumented feature.)

Consider using:

  env CFLAGS=$(CFLAGS) /usr/bin/dtrace  -o Python/pydtrace.o -G -s [...]

Comment 5 Charalampos Stratakis 2025-03-10 19:13:23 UTC
(In reply to Frank Ch. Eigler from comment #4)
> The /usr/bin/dtrace script doesn't have a command line option to pass along
> extra hardening cflags.  However, it observes the $CLFAGS environment
> variable and relays those to the inferior gcc.  (This is an accidentally
> undocumented feature.)
> 
> Consider using:
> 
>   env CFLAGS=$(CFLAGS) /usr/bin/dtrace  -o Python/pydtrace.o -G -s [...]

From some preliminary testing this seems to be working, thanks!

I'll do some more testing to verify the results everywhere and propose it upstream (although systemtap support is kinda half broken at the moment).

Is there any place where this could be documented?

Comment 6 Frank Ch. Eigler 2025-03-10 21:21:53 UTC
I'll plop it into upstream man pages right away.

Comment 8 Charalampos Stratakis 2025-03-10 23:53:21 UTC
Thanks! Changing the component to the latest Python in Fedora.

Comment 9 Charalampos Stratakis 2025-03-31 23:44:03 UTC
We can wait for the next release for this.


Note You need to log in before you can comment on or make changes to this bug.