Skip to content

openbsd: ensure we link to the built libperl.a, not the system libperl.a #23265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: blead
Choose a base branch
from

Conversation

tonycoz
Copy link
Contributor

@tonycoz tonycoz commented May 7, 2025

When building with gcc, lib/ExtUtils/t/Embed.t would link against the system libperl.a rather than the newly built libperl.a.

Due to the limited API used by the sample code this typically didn't crash, but some configuration changes could result in a crash or a link error.

For OpenBSD, change the link options to more closely match those used when building the perl executable, which results in linking against the correct library.

Fixes #22125

Also adds a test to ensure we are linking against the correct libperl.

Smoke reports from before a trivial rebase at https://perl.develop-help.com/?b=smoke-me%2Ftonyc%2F22125-openbsd-embed


  • This set of changes requires a perldelta entry, and it is included.

@jkeenan
Copy link
Contributor

jkeenan commented May 7, 2025

@tonycoz, thanks for continuing to investigate this. Could you rebase your smoke-me branch and push this new code to that branch? That way, @cjg-cguevara's smoker will pick up the branch.

@afresh1, can you take a look at this p.r.? Thanks.

@jkeenan
Copy link
Contributor

jkeenan commented May 7, 2025

@tonycoz: I fetched your p.r. and built a perl locally per the following:

$ uname -mrs
OpenBSD 6.9 amd64
$ gcc --version
gcc (GCC) 4.2.1 20070719 
$ gitcurr
gh-23265-tonycoz-22125-openbsd-embed-20250507
$ ./perl -Ilib -V:config_args
config_args='-des -Dusedevel -Dcc=gcc -Accflags=-DPERL_RC_STACK -DDEBUG_LEAKING_SCALARS';
$ ./perl -Ilib -v | head -2 | tail -1
This is perl 5, version 41, subversion 13 (v5.41.13 (v5.41.12-41-g060adda81e)) built for OpenBSD.amd64-openbsd

This configuration was the first one I discussed in #22125. All tests PASSed. So that's a very good sign. I will want to re-test this with clang10 and g++. However, as previously reported my OpenBSD-VM version is obsolete, so we'll need feedback from people who have more up-to-date versions of the platform and its C-compilers. Having your p.r. code in the smoke-me branch will be very helpful for this.

@tonycoz
Copy link
Contributor Author

tonycoz commented May 7, 2025

Having your p.r. code in the smoke-me branch will be very helpful for this.

I pushed it to the smoke-me, https://perl.develop-help.com/?b=smoke-me%2Ftonyc%2F22125-openbsd-embed we're just waiting for results now.

@jkeenan
Copy link
Contributor

jkeenan commented May 7, 2025

I've also gotten a PASS with the following configuration:

$ ./perl -Ilib -V:config_args
config_args='-des -Dusedevel -Dcc=clang -Accflags=-DPERL_RC_STACK -DDEBUG_LEAKING_SCALARS';

Am beginning a smoke-test run with my customary configurations. That will take several hours. Note that I haven't looked at the code changes at all -- only the test results.

@afresh1
Copy link
Contributor

afresh1 commented May 7, 2025

I should be able to run tests with this. Will have to remember which architectures I have that still use gcc :-)

object was built with and the perl that C<libperl> was built with.

This can be used to ensure that these match and produces a more
diagnosable than random crashes and mis-behaviour.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a word or two missing after diagnosable. diagnosable behavior, perhaps?

@Leont
Copy link
Contributor

Leont commented May 9, 2025

Intuitively, it seems wrong to me that this is OpenBSD specific code. Are we sure we're fixing this in the right place?

@tonycoz
Copy link
Contributor Author

tonycoz commented May 9, 2025

Intuitively, it seems wrong to me that this is OpenBSD specific code. Are we sure we're fixing this in the right place?

Smoke testing didn't find anything else tripping the added version check.

There may be other systems that trip this, but I'd rather not risk breaking this test for other systems by making the change for other systems too without evidence that it's needed.

@ap
Copy link
Contributor

ap commented May 9, 2025

Both points seem reasonable. We (PSC) are thinking we should ship this patch as is for now, but we also want to pick this up early next cycle and investigate whether we can make this change across the board without limiting it to OpenBSD.

@Leont
Copy link
Contributor

Leont commented May 9, 2025

Both points seem reasonable. We (PSC) are thinking we should ship this patch as is for now, but we also want to pick this up early next cycle and investigate whether we can make this change across the board without limiting it to OpenBSD.

Yeah that sounds reasonable to me.

@afresh1
Copy link
Contributor

afresh1 commented May 9, 2025

I should be able to run tests with this. Will have to remember which architectures I have that still use gcc :-)

Time got away from me, it won't be this week.

@afresh1
Copy link
Contributor

afresh1 commented May 16, 2025

On my machine where it is easy to build a smoke-me perl:


This is perl 5, version 41, subversion 13 (v5.41.13 (v5.41.12-41-g060adda81e)) built for OpenBSD.sparc64-openbsd

with

./Configure -des -Dusedevel -Dcc=gcc -Accflags="-DPERL_RC_STACK -DDEBUG_LEAKING_SCALARS"

I get:

Failed 3 tests out of 2664, 99.89% okay.
        ../lib/locale.t
        porting/authors.t
        run/locale.t

Which does not include failures from lib/ExtUtils/t/Embed.t.

tonycoz added 3 commits June 25, 2025 09:29
Issue Perl#22125 detected that we weren't linking the correct library with
the embedded test with gcc on OpenBSD, so add an API to perform a
sanity check by comparing the size of the perl interpreter
structure (or its size if it was a structure) and expected perl API
version between those seen in the binary and those compiled into
libperl.
When building with gcc, lib/ExtUtils/t/Embed.t would link against
the system libperl.a rather than the newly built libperl.a.

Due to the limited API used by the sample code this typically didn't
crash, but some configuration changes could result in a crash or a
link error.

For OpenBSD, change the link options to more closely match those
used when building the perl executable, which results in linking
against the correct library.

Fixes Perl#22125
@tonycoz tonycoz force-pushed the 22125-openbsd-embed branch from 060adda to 66ef0b8 Compare June 24, 2025 23:35
@tonycoz
Copy link
Contributor Author

tonycoz commented Jun 24, 2025

rebased to clear the conflict

if (interp_size != sizeof(PerlInterpreter)) {
/* detects various types of configuration mismatches */
/* diag_listed_as: Mismatch between expected and libperl %s */
Perl_croak(aTHX_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a croak_nocontext(), this fn is max run 1x a process. the croak branches are 0 Kelvin code and will never execute w/o C dev user error, the performance of executing while (1) { eval { croak("heap corruption"); }; } is illogical. smaller machine code is the correct goal.


void
Perl_api_version_assert(size_t interp_size, void *v_my_perl,
const char *api_version) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not switch const char *api_version to PERL_BCDVERSION which is an integer? The only reason xs_handshake() uses a const char *api_version is hysterical raisins with pre-existing EU::PXS code gen behavior and hysterical raisins over string equality method of operation in the IEEE vs W3C vs WHATWG vs IETF version.pm standards war (example: fb79428 ).

Since my TLDR understanding of v-strings and version string equality and comparison logical operations is, v-str and ver.pm == > < logical operations, should just be labeled abstract undefined behavior <=> operator if your writing code for CPAN or writing PP code that will execute on more than 1 build number of libperl.so. Or will execute on any /bin/perl other than your employer's official corporate "Perl on Docker" image.

So b/c there is so much soap drama with non-floating point version numbers, and PERL_API_VERSION, is a 3 '.' dots thing, which means is part of the standards war, I decided to keep the const char * null_term_perl_api_ver parameter for xs_handshake. The drama with 3 '.' dots and v prefix was quite active 10 years ago. And xs_handshake() was supposed to be "low impact" or "not invasive" or minimalist in design.

using const char * null_term_perl_api_ver instead of a U32 aka PERL_BCDVERSION, in the prototype of xs_handshake() would've allowed macro PERL_API_VERSION_STRING to be string "5.40.0-armbe-hurd-newlib-no_rms-lgbtqabi" or "5.40.0-mipsle-muscl-no_afferoabi". P5P would never modify the PERL_API_VERSION_STRING macro to be "5.40.0-mipsle-muscl-no_afferoabi", but P5P can't send lawyers and SWAT/GIGN to force random Linux/BSD distros projects to reverse their patches to Perl on their published .isos.

So that was reason # 2 why I left it as a char * and not a U32. Minimalist, most flexible for the future, wait and see what happens, dont do an over engineered forklift refactor.

AFAIK the ELF spec is mostly written where all the behaviors are "optional" to implement, but if the feature/constant/bit in a bitfield/C struct/member in a struct, is implemented by a vendor, then the feature/constant/bit in a bitfield/C struct/member in a struct has "defined behavior" in ELF. ELF isn't like Windows and its PE format, where there is ONE WAY TO DO IT, NO EXCEPTIONS! B/c Windows and PE mandate forever backwards ABI compatibility to the "i386 pre-release SDK" from Oct 1992.

I don't believe ELF binaries compiled in the 1980s for i386 are copy+paste+double click executable on Ubuntu/Freebsd/Fedora in 2025. besides, the Linux kernel doesn't even know what an ELF file is, and isn't aware that the ELF spec exists.

From Linux's viewpoint, ELF is just a random 3rd party kernel driver someone wrote a while back. You can disable ELF support in Linux if you prefer Windows PE .exes/.dlls or MachO files more than the ELF format.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_elf_fdpic.c#n92

https://docs.kernel.org/admin-guide/binfmt-misc.html

So yeah, I have no clue if some Unix OS will add a dozen random tokens/identifiers/english lang words, to the PERL_API_VERSION_STRING "5.40.0" macro. I don't think any Linux/BSD distro has randomly decided to start patching PERL_API_VERSION_STRING in their system perls, in the last couple of years, so at this point in 2025, I would say to use PERL_BCDVERSION U32 instead here. Also this code is the REVERSE of xs_handshake(), the consumer and producer were flipped around. This is a .bin file under full end user control compiled by the end user, loading a random unknown libperl.so file into address space. The end user is using the cryptographic-ally secure P5P code base (aka git + SSL + github.com), the end user didn't checkout the patched system perl and its exact Configure settings from their Distro vendor (canonical)'s RCS. So P5P codebase and the end user's fork of the P5P repo, have no reason to change macro PERL_API_VERSION_STRING to "5.40.0-mipsle-muscl-no_afferoabi" for some real or imaginary engineering reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So yeah, I have no clue if some Unix OS will add a dozen random tokens/identifiers/english lang words, to the PERL_API_VERSION_STRING "5.40.0" macro. I don't think any Linux/BSD distro has randomly decided to start patching PERL_API_VERSION_STRING in their system perls, in the last couple of years, so at this point in 2025, I would say to use PERL_BCDVERSION U32 instead here. Also this code is the REVERSE of xs_handshake(), the consumer and producer were flipped around. This is a .bin file under full end user control compiled by the end user, loading a random unknown libperl.so file into address space. The end user is using the cryptographic-ally secure P5P code base (aka git + SSL + github.com), the end user didn't checkout the patched system perl and its exact Configure settings from their Distro vendor (canonical)'s RCS. So P5P codebase and the end user's fork of the P5P repo, have no reason to change macro PERL_API_VERSION_STRING to "5.40.0-mipsle-muscl-no_afferoabi" for some real or imaginary engineering reason.

15 minutes after I speak of the devil, and the devil himself appears in production perl code. See this ticket.

#23355

Someone was NOT USING the cryptographically signed .git P5P's Perl code base, but their vendor's [Fedora 501(c)(3) LLC] cryptographically signed .git repo that is a fork of P5P codebase, to do their own personal Perl interp core hacking adventures. And then they ran into problems using the code base of Fedora's fork of Perl 5 code base, then came to this GH, looking for help, for a fork of Perl that P5P isn't responsible for. Out of civility, P5P volunteers will obviously offer advice to that person, even though P5P is not legally responsible for a Linux Distro's vendor patches to mainline Perl 5 VM. But still, 15 mins ago I said nobody will ever do that, and someone just did that.

@@ -196,6 +209,8 @@ int main(int argc, char **argv, char **env) {
perl_construct(my_perl);
PL_exit_flags |= PERL_EXIT_WARN;

PERL_API_VERSION_ASSERT;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not move PERL_API_VERSION_ASSERT; to right below my_perl = perl_alloc();. me knowing various permutatoins of crashing ancient modern perl5xx.dll permutations, this test code/demo code already segved or caused heap corruption before reaching the PERL_API_VERSION_ASSERT; statement.

PL_exit_flags |= PERL_EXIT_WARN;

What is grammar token/src code ascii string PL_exit_flags in machine code view?

Is PL_exit_flags a Perl 5.6/5.8/5.10 symbian/win32/win16/cray style
extern "C" int * Perl_Isolation_PL_exit_flags(void);
is it?
extern "C" int * Perl_Isolation_PL_exit_flags(my_perl);

is it? IIRC below is AKA dVAR; macro,
extern "C" int * Perl_Isolation_PL_exit_flags(my_env, my_perl);

is it?
extern "C" int PL_exit_flags;

is it?
extern int __@@C$PLUS$__PLUSSS$666@_QWERTY@_PL_exit_flags@__;

is it?
*(int*)( ((char*)my_perl) + 0x47c)

is it?
extern "C" int __$SONAME@PL_exit_flags$libperl.so.5.40.1.0083.6798;

What did the end user C dev really write (hex dump wise) with ascii string PL_exit_flags |= PERL_EXIT_WARN; ?

Lets do our best to print in english to STDERR before LD_LAZY_LINK insta-KILL the process and fills the users console with unreadable CPU GPR and FP register hex dumps and leaves a 30MB core dump file of gibberish on the end users machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lib/ExtUtils/t/Embed.t: failures on OpenBSD when compiling with gcc but not with clang
6 participants