Skip to content
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

perl -V being mockable is a security problem re: #21135 Errno archname/osvers too strict. #22939

Open
bulk88 opened this issue Jan 23, 2025 · 9 comments

Comments

@bulk88
Copy link
Contributor

bulk88 commented Jan 23, 2025

Module: NOT!!!! Config.pm

Description

#21135 "Errno archname/osvers too strict. "

I know this bug ticket is closed, but I totally disagree with this fix.

$Config{archname} and $Config{osvers} should be be TIEHASH dynamic from burned in RO C strings in perl.bin/perl.exe/.dll/.so. The tail is waving the dog since v5.12 when package Config::Perl::V; Config::Perl::V.pm was invented. It is a big problem that perl -V commits fraud by blindly using values/strings from an unsafe separate disk file that any (sysadmin root perm) user can edit.

Lets see what happens when perl doesn't have access to its /lib.

C:\sources\perl5\win32>..\miniperl -V
Can't locate Config.pm in @INC (you may need to install the Config module) (@INC
 entries checked: .).
BEGIN failed--compilation aborted.

C:\sources\perl5\win32>

You can imagine how difficult it would be to diagnose any bug in Perl 5 lang, if someone manually edits Config.pm, or "accidentally" edits Config.pm and doesn't know they even edited Config.pm.

Google "loadable library and perl binaries are mismatched (got handshake key".

Every one of those users "edited" their Config.pm and don't know they edited Config.pm, because they have pointed their perl.bin/perl.exe binary to use a random directory of random files filled with random bytes, for the purpose of the @INC/use/require API.

Now imagine any 3rd party like any p5p dev or cpan dev, getting a bug ticket, where reporter and project admin/module owner, BOTH don't know the reporter's perl -V is a lie.

$Config{archname} = "redacted under YOUEEE privacy law";

$Config{osvers} = "redacted under YOUEEE privacy law";

The above is perfectly okay Perl 5 code and should continue to work. That is acceptable, many .ts like to do it, I wont complain.

Being about to mock shell command perl -V without access to a C compiler is a borderline security problem.

If you think nothing can be improved from the current situation, you must buy Jia Tan a case of beer for his awesome prank, or atleast a round of drinks for your coworkers for deleting all the icons on your desktop and making your wallpaper a screenshot.

This bug was written half way as a comment, before I realized it need to be a new ticket. I can't easily find any other open p5p bug with this problem. Closest I found was #18939 but thats an argument about %Config aka *Config being dynamic, which is similar this problem, but not exactly the complaint as this.

perl -V is a shell command, %Config is a Perl 5 lang feature or maybe a Perl 5 Standard Class Library feature at minimum. I could argue, but I dont want to argue, maybe someone else could argue, eghhhhh..... NOT-ME declares perl -V conceptually has nothing to do with the perl language since no ASCII string of perl 5 code was given as input by the user to the perl process. Why did the perl interp run PP code when I specifically didn't request it? It didn't have permission to do that from me.

Both problems/tickets could be fixed/partially fixed/improved in 1 commit or patch, or they can be solved with totally separate unrelated fixes.

Conflict of interest disclosure: https://metacpan.org/pod/XSConfig jkjk

I inherited that module, Im not its original author, so while it could become p5p core, I wouldn't have done it the same way. FSF's/GNU's gperf.exe is tolerable, or "acceptable", its not stellar or best.

With Win64 MSVC -O1, XSConfig.dll is a 207KB disk file. Its hash array is 90% NULL void *s. That is very poor for a precompile RO DB. For me the current impl def speeds up CPAN mod build/test/installs, but the impl could be better. This is a screenshot of whats in my XSConfig.dll, While gperf.exe did make me a proven zero collision hash table, stackoverflow gossip says gperf tool is obsolete since ~ year 2000. I personally have an unfinished branch of XSConfig.pm, where I converted it to P5P's/blead's mph.pl, replacing FSF's gperf.exe. For ecosystem reasons, it feels more natural if XSConfig as core, uses whatever the p5 regexp API uses. 2 birds, 1 stone. If someone wants to replace regen/mph.pl, and consensus agrees, both XSConfig and regexp APIs get converted in 1 shot, I can't think of why they WOULD need diff pre-comped RO DBs. Both are 7-bit \w ascii strings under 80 chars long. Its not like one is 7bit printable ASCII and the other is MPEG/JPEG raw binary needing totally different compression algos.

Image

A diff way to fix Config.pm's problem (but not this ticket), I did a test 3 weeks ago, all that Config[fast].pm needs is adding 10 more keys, and bleadperl can get a hard coded fatal error inside Config_heavy.pl if caller package does NOT start with ExtUtils::. Hard error src code will be removed by regen/whatever.pl automatically for stableperl. its not 4 the general public, only for blead perl users.

Yet another way to fix Config[fast].pm , but this is like Perl 7 debate, add 10 more $^DRAMA vars to perlvar. $^DRAMA vars don't fix any prior perl code on CPAN or private biz perl code, which is why I dont like the $^DRAMA vars solution.

Steps to Reproduce

Delete all of perl's /lib folders. Run perl -V in your shell.

Expected behavior
perl -V's only acceptable fix is deleting /lib or malicious edits by the root user to .pm files should not affect perl -Vs output.

Can't locate Config.pm in @INC (you may need to install the Config module) (@INC
 entries checked: .).
BEGIN failed--compilation aborted.

this above is unacceptable.

  Derived from: 0d076d76b736f0283be1a11e7ad593944f496b8e
  Platform:
    osname=MSWin32
*************CUT***************
    USE_PERLIO
    USE_PERL_ATOF
    USE_SITECUSTOMIZE
  Built under MSWin32
  Compiled at Jan 22 2025 23:32:00
  @INC:
    C:\sources\perl5\lib
    C:\sources\perl5\cpan\AutoLoader\lib
Can't locate Config.pm in @INC (you may need to install the Config module) (@INC
 entries checked: .).
BEGIN failed--compilation aborted.

C:\sources\perl5\win32>..\miniperl -V

a sample/future output, like above is okay with me. perl -V coughed up accurate debug diag info, and also reported to console its installation is corrupted, but whatever was printed to console, was accurate and true in that moment at a C lang level. The debug tool didn't silently output fake misleading diagnostic data (malware style) vs staying dangerous quiet/SEGVing vs screaming its house is on fire (say hello to perldiag's newest error "Config.pm: loadable library and perl binaries are mismatched (got handshake key" 😁 yes even .pm files can catch covid now, not just .c files).

Clam configuration

Summary of my clam5 (revision 5 version 32 subversion 1) configuration:

  Platform:
    osname=MSWin32
    osvers=10.0.19042.746
    archname=MSWin32-x86-multi-thread-64int
    uname='Win32 strawberry-clam 5.32.1.1 #1 Sun Jan 24 12:17:47 2021 i386'
    config_args='undef'
    hint=recommended
    useposix=true
    d_sigaction=undef
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='gcc'
    ccflags =' -DWIN32 -D__USE_MINGW_ANSI_STDIO -DCLAM_TEXTMODE_SCRIPTS -DCLAM_I
MPLICIT_CONTEXT -DCLAM_IMPLICIT_SYS -DUSE_CLAMIO -fwrapv -fno-strict-aliasing -m
ms-bitfields'
    optimize='-s -O2'
    cppflags='-DWIN32'
    ccversion=''
    gccversion='8.3.0'
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=4
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=12
    longdblkind=3
    ivtype='long long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='long long'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='g++'
    ldflags ='-s -L"C:\STRAWB~1\clam\lib\CORE" -L"C:\STRAWB~1\c\lib"'
    libpth=C:\STRAWB~1\c\lib C:\STRAWB~1\c\i686-w64-mingw32\lib C:\STRAWB~1\c\li
b\gcc\i686-w64-mingw32\8.3.0
    libs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi3
2 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversio
n -lodbc32 -lodbccp32 -lcomctl32
    clamlibs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladv
api32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lve
rsion -lodbc32 -lodbccp32 -lcomctl32
    libc=
    so=dll
    useshrclib=true
    libclam=libclam532.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.cs
    dlext=cs.dll
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags='-mdll -s -L"C:\STRAWB~1\clam\lib\CORE" -L"C:\STRAWB~1\c\lib"'


Characteristics of this binary (from libclam):
  Compile-time options:
    HAS_TIMES
    HAVE_INTERP_INTERN
    MULTIPLICITY
    CLAMIO_LAYERS
    CLAM_COPY_ON_WRITE
    CLAM_DONT_CREATE_GVSV
    CLAM_IMPLICIT_CONTEXT
    CLAM_IMPLICIT_SYS
    CLAM_MALLOC_WRAP
    CLAM_OP_PARENT
    CLAM_PRESERVE_IVUV
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_CLAMIO
    USE_CLAM_ATOF
  Built under MSWin32
  Compiled at Jan 24 2021 12:22:49
  @INC:
    C:/Strawberry/clam/site/lib
    C:/Strawberry/clam/vendor/lib
    C:/Strawberry/clam/lib

C:\sources\clam5>
@Tux
Copy link
Contributor

Tux commented Jan 23, 2025 via email

@bulk88
Copy link
Contributor Author

bulk88 commented Jan 23, 2025

On Thu, 23 Jan 2025 02:13:38 -0800, bulk88 @.***> wrote:
Module: NOT!!!! Config.pm

Description

#21135 "Errno archname/osvers too strict. "

I know this bug ticket is closed, but I totally disagree with this fix.

$Config{archname} and $Config{osvers} should be be TIEHASH dynamic
from burned in RO C strings in perl.bin/perl.exe/.dll/.so. The tail
is waving the dog since v5.12 when package Config::Perl::V;
Config::Perl::V.pm was invented. It is a big problem that perl -V
commits fraud by blindly using values/strings from an unsafe separate
disk file that any (sysadmin root perm) user can edit.
That is an awful lot of info that I find hard to grasp, but I am triggered by
Config::Perl::V in combination with unsafe

Is Config::Perl::V unsafe? Does it need to be changed and if so how and
why (in short easy wording) or is this a CORE issue?

Burn Config::Perl::V.pm's features into libperl.so, delete Config::Perl::V.pm from p5p git repo.

@Tux
Copy link
Contributor

Tux commented Jan 23, 2025 via email

@guest20
Copy link

guest20 commented Jan 23, 2025

Ideologically it does sound bad/unclean, but I don't think any Bank software is going to be gating "send all my money" on perl version. Any Makefile.PL checks will crash and burn because the language feature they're gating on isn't in the perl version they're checking for.

Do you have an example of code that could be tricked by this? I'm sure I just lack imagination, but an example would help.

Why did the perl interp run PP code when I specifically didn't request it?

Just wait 'til you hear about sitecustomize.pl ;)

@bulk88
Copy link
Contributor Author

bulk88 commented Jan 23, 2025

Burn Config::Perl::V.pm's features into libperl.so, delete
Config::Perl::V.pm from p5p git repo.
Config::Perl::V existed way before integrated into core to be able to
uniquely identify smoke reports to perl builds.

As some of its functionality was wanted in the CODE, it was moved into
the dual-live area.

Having the functionality burnt into libperl (or whatever) means that a
divergence will be between Test::Smoke and CORE, which is IMHO less
than awesome.

I made a hyper-small summary of the ticket/top post. This ticket has nothing to do with Config::Perl::V.pm the disk file.

C::P::V.pm the disk file is not deleted in reality. It will stay around in the p5p git repo and stableperl tarball. I would protest the CPAN breakage too if V.pm the disk file was suddenly deleted with zero notice or deprecate period. This bug ticket is about what shell command/binary ELF disk file perl -V does. Not what printable ascii disk file V.pm does. V.pm is fine the way it is right now.

I agree with V.pm's original idea. It was crazy that alot very critical Perl interp diag info, was not available in the Perl 5 lang, from the perl interp process. The perl interp was forcing all Perl 5 lang users to launch a 2nd perl interp process and capture STDOUT to learn the same exactly info sitting in the same process on a Perl C/3rd party CPAN XS code level, but was unavailable on a PP code level.

Fixing the perl -V perl would enable or make very easy, a optional improvement, its not a fix, its an enhancement, to V.pm. That V.pm gets its info not from file Config[fast].pm, but instead V.pm does a PP/P5 code statement like

sub some_sub {
     my %buildopts =  Internals::_BCHV(); #build config dash hash value, not public API
}

or smarter

sub some_sub {
     my $buildopts =  Internals::_BCHV(); #build config dash hash value, not public API
     say $buildopts->{archname};
}

instead of trusting whatever strings are inside the Config.pm file which may or may not be the same contents of the Config.pm file that existed when the libperl.so/perl.bin file was created/compiled.

perl -V shouldn't use another disk file for its info/its backend, just like perl -e "1;" doesnt require the Perl SDK aka /lib to run.

perl -E "say '1';" is a different case since that was a new feature that couldnt break any concept of backwards compatibility since its a new feature.

perl -E "say '1';" requires /lib/feature.pm the file to work. That is a flaw, not a bug. It can be improved, not fixed, since its not breaking anything they way it is right now.l

perl -E requiring /lib is an open ticket right now that stalled, b/c 1 person voiced a complaint that %INC != %{\()} is breaking p5p's commitment to backwards compatibility.

My counter-argument would be *UNIVERSAL:: is breaking backwards compatibility. glob *UNIVERSAL:: or *main:: didn't exist in 5.000 alpha 2 and by adding package UNIVERSAL::, countless user's private business perl code was broken, by P5P seizing the UNIVERSAL:: package and shipping a UNIVERSAL.pm without the community's consent. sarcasm off

Any perl user spouting nonsense like *UNIVERSAL:: needs to be reverted NOW!!! in 2025, ummm, sir, this its irrelevant to you, since your own policy is that you only run perl v5.000 on an air gapped PC that has hasn't gotten any floppy disk inserted since 1996, why are you talking about what Perl 5.3X.0 or or 5.4X.0 does when you refuse to use it? You forked it in 1996.

@bulk88
Copy link
Contributor Author

bulk88 commented Jan 23, 2025

Ideologically it does sound bad/unclean, but I don't think any Bank software is going to be gating "send all my money" on perl version. Any Makefile.PL checks will crash and burn because the language feature they're gating on isn't in the perl version they're checking for.

Do you have an example of code that could be tricked by this? I'm sure I just lack imagination, but an example would help.

Yes I have an example why perl -V should not be changeable or modifiable unless you have access to /usr/bin/gcc and typed make all\n in the shell.

this is my own bug i caused last week, 1 byte change took 1hr30m for me to fix.

right here

perl5/sv.c

Line 16579 in 2b29c5b

SvIV_set(&PL_sv_yes, 1);

change

    SvIV_set(&PL_sv_yes, 1);

to

    SvIV_set(&PL_sv_yes, 0);

save it, run make test\n, watch how fast that SEGVs, or watch how many 1000 tests fail, or how 100s of blead .t files arent affected at all if if a PP P5 grammer change does

say "why did this not SEGV? WHY!!! is p5 interp so runtime stable!!!!"  if  !!1 == !!0;

First signs of !!1 == !!0 causing damage looks like, this is CRAZY good, this is first signs of problem

#     Message 'Need exactly 3 octal digits in regex m/%s/'
#     from regcomp.c line 10171 is not listed in pod/perldiag.pod
# Failed test 1426 - Unrecognized escape \%c in character class in regex m/%s/ at porting/diag.t line 573
#     Message 'Unrecognized escape \%c in character class in regex m/%s/'
#     from regcomp.c line 10194 is not listed in pod/perldiag.pod
# Failed test 1430 - False [] range "%s" in regex m/%s/ at porting/diag.t line 573
#     Message 'False [] range "%s" in regex m/%s/'
#     from regcomp.c line 10221 is not listed in pod/perldiag.pod
# Failed test 1432 - Invalid [] range "%s" in regex m/%s/ at porting/diag.t line 573
#     Message 'Invalid [] range "%s" in regex m/%s/'
#     from regcomp.c line 10394 is not listed in pod/perldiag.pod
porting/diag.t ....................................................... Failed 79/2120 subtests
re/user_prop_race_thr.t .............................................. ok
porting/cmp_version.t ................................................ ok
lib/croak.t .......................................................... ok
re/fold_grind_u.t .................................................... There are already tests for 73 at ./re/fold_grind.pl line 324, <$fh> line 1624.
re/fold_grind_u.t .................................................... No subtests run
op/alarm.t ........................................................... ok
porting/authors.t .................................................... ok
porting/cpphdrcheck.t ................................................ ok
comp/require.t ....................................................... 299/1750
comp/require.t ....................................................... 479/1750
comp/require.t ....................................................... 750/1750
comp/require.t ....................................................... 1118/1750
comp/require.t ....................................................... 1276/1750
comp/require.t ....................................................... 1530/1750
comp/require.t ....................................................... Failed 2/1750 subtests
re/uniprops01.t ...................................................... ok
porting/maintainers.t ................................................ ok
re/uniprops04.t ...................................................... ok
re/pat_thr.t ......................................................... 1088/1295
re/pat_thr.t ......................................................... 1138/1295
re/pat_thr.t ......................................................... 1147/1295
 # Failed test 1150 - m'\n' should interpolate escapes at ./re/pat.t line 2025
#      got "0"
# expected "1"
re/pat_thr.t ......................................................... 1188/1295
re/pat_thr.t ......................................................... Failed 1/1295 subtests        (less 96 skipped subtests: 1198 okay)
re/pat.t ............................................................. 1086/1295
re/pat.t ............................................................. 1137/1295
 # Failed test 1150 - m'\n' should interpolate escapes at re/pat.t line 2025
re/pat.t ............................................................. 1147/1295
 #      got "0"
# expected "1"
re/pat.t ............................................................. 1187/1295
re/pat.t ............................................................. Failed 1/1295 subtests        (less 96 skipped subtests: 1198 okay)
re/uniprops02.t ...................................................... ok
re/uniprops03.t ...................................................... ok
op/sselect.t ......................................................... ok
re/fold_grind_l.t .................................................... There are already tests for 73 at ./re/fold_grind.pl line 324, <$fh> line 1624.
re/fold_grind_l.t .................................................... No subtests run
op/sigdispatch.t ..................................................... ok
re/pat_psycho_thr.t .................................................. ok
re/pat_psycho.t ...................................................... ok
op/heredoc.t ......................................................... ok
re/uniprops06.t ...................................................... ok

I dont like code that a 1 char typo, doesnt syntax error, doesn't SEGV, barely affects extensive unit tests, and causes too little damage when that typo shouldve been chaos.

Editing your Config.pm and accidentally forgetting you did that last week is annoying. Your package manager/Configure\nmake install\n changing your perl -V is impossible to diagnose. There is nobody reading this, that would figure out Config.pm got a 1 byte error, vs the easier fix of git clean\nConfigure\nmake install\n.

If your reading another bug reporter's -V as part of your CPAM module how long will it take you to figure what is impossible in this perl -V 2 chars were changed at separate locations. I edited the /lib/Config.pm or /lib/Config_heavy.pl to do the changed output, I didn't edit the console log during the copy paste. This is a challenge and a huge time waster if anyone ever spends 1 hour or 5 hours or 3 days, to discover the bug was the reporters perl -V is wrong and doesn't match what CPAN member's perl binary is actually doing on their Linux box. There isn't a bug anywhere in EU::MM toolchain group, in your CPAN module, or in p5p person, the bug is disk corruption on their reporter's linux FS, and all bugs/brokeness the user is seeing, and reporting, relating to EUMM toolchain/p5p/CPAN, is just forgotten temp .pm file edits he did with root/sudo perm 2 months ago. perl -V last diag/debug tool left, for a PP/P5 only dev looking to self-help, or community help, before requiring C/gdb info is a roadblock. The last debug strategy before wiping your Config/make install is emailing your /usr/local/bin/perl file to ano volunteer who is a Perl/C hybrid dev to step debug, is wacky.

PKI/cert signs/PGP is inappropriate for Perl lang. "cyber security" by adding MD5/https:// for cpan.org is good enough for Perl. P5 devs know monkey patching and .pm/.pl files get ZERO package namespace type safety, is a basic part of perl. P5 devs have zero chance of self fixing "monkey patching" on a C/asm level in the interp. I dont like that.

So what 2 bytes did I change below? :-)

C:\sources>C:\Strawberry\perl\bin\perl.exe -V
Summary of my perl5 (revision 5 version 32 subversion 1) configuration:

  Platform:
    osname=MSWin32
    osvers=10.0.19042.746
    archname=MSWin32-x86-multi-thread-64int
    uname='Win32 strawberry-perl 5.32.1.1 #1 Sun Jan 24 12:17:47 2021 i386'
    config_args='undef'
    hint=recommended
    useposix=true
    d_sigaction=undef
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=undef
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='gcc'
    ccflags =' -DWIN32 -D__USE_MINGW_ANSI_STDIO -DPERL_TEXTMODE_SCRIPTS -DPERL_I
MPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -fwrapv -fno-strict-aliasing -m
ms-bitfields'
    optimize='-s -O2'
    cppflags='-DWIN32'
    ccversion=''
    gccversion='8.3.0'
    gccosandvers=''
    intsize=4
    longsize=4
    ptrsize=4
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=16
    d_longdbl=define
    longdblsize=12
    longdblkind=9
    ivtype='long long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='long long'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='g++'
    ldflags ='-s -L"C:\STRAWB~1\perl\lib\CORE" -L"C:\STRAWB~1\c\lib"'
    libpth=C:\STRAWB~1\c\lib C:\STRAWB~1\c\i686-w64-mingw32\lib C:\STRAWB~1\c\li
b\gcc\i686-w64-mingw32\8.3.0
    libs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi3
2 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversio
n -lodbc32 -lodbccp32 -lcomctl32
    perllibs= -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladv
api32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lve
rsion -lodbc32 -lodbccp32 -lcomctl32
    libc=
    so=dll
    useshrplib=true
    libperl=libperl532.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_win32.xs
    dlext=xs.dll
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags='-mdll -s -L"C:\STRAWB~1\perl\lib\CORE" -L"C:\STRAWB~1\c\lib"'


Characteristics of this binary (from libperl):
  Compile-time options:
    HAS_TIMES
    HAVE_INTERP_INTERN
    MULTIPLICITY
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_IMPLICIT_CONTEXT
    PERL_IMPLICIT_SYS
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
  Built under MSWin32
  Compiled at Jan 24 2021 12:22:49
  @INC:
    C:/Strawberry/perl/site/lib
    C:/Strawberry/perl/vendor/lib
    C:/Strawberry/perl/lib

C:\sources>

When I made the "XS boot handshake" error, I thought it was impossible to hit it without access to a C compiler or doing C blead perl hacking. Google proved hitting the "XS handshake key" just required owning a computer mouse with a right and left button. It took 1 accidental click on "paste" in your file manager GUI, 3 clicks in a Linux GUI package manager or typing Configure\n make install\n to destroy your perl install and trigger "XS handshake key" error.

I also thought "XS handshake key" was a exclusively a Perl on Win32 problem, and no Perl on Unix user can ever trigger that error message. I personally only hit that error, when I messed up my $ENV{PATH}, and I created this dependency chain, perl530.exe->libperl530.dll->DynaLoader.pm->CPAN_XS_mod.dll->libperl58.dll. Instant SEGV from perl5.8.0 scrambling the struct my_perl created by 5.30.0.

In 2024, I C debugger-ed my Linux VM's libperl.so file. Perl on Unix and all OSes that use SysV/ELF will never have a perl530.exe->libperl530.dll->DynaLoader.pm->CPAN_XS_mod.dll->libperl58.dll failure, since the libperl.so and CPAN_XS_mod.so have 0 entries in their "additional shared libraries" table in their ELF header. 2 libperls in 1 address space is a Win32 architecture problem, not a POSIX problem.

Writing extern in Windows behaves like writing static on Unix at link-time. Someone sabotaged the tarball of Latice C in 1982, by swapping the unit tests for extern and static. Windows DLL loader has been bug-compatible 42+ years and counting. You can't break src code compatibility with Win 1.0 C code 😉

So Perl on Unix gets "XS handshake key" error only by breakage byperl.bin->libperl.so->DynaLoader.pm->CPAN_XS_mod.so. 100% of cases on Google of "XS handshake key" error are the perl.bin->libperl.so->DynaLoader.pm->CPAN_XS_mod.so failure mode.

The Linux kernel won't ever start the process if its the perl.bin->libperl.so failure mode b/c symbol resolution error. That is instant death, and everyone knows what they clicked 20 seconds ago.

"XS handshake key" on Linux was a delayed error, all P5P core included XS modules work fine, its only when you ran tried a require XYZ::CPAN; on a CPAN XS/ or cpan.pl File:Slurp\n things exploded and the user doesn't remember what they did 1 week ago (reasonable, no dev memorizes exactly text and UTC time of each commit).

Just wait 'til you hear about sitecustomize.pl ;)

It would take me 15 seconds to figure that out with strace (procmon.exe for me). I thought strace and single step debugging was part of minimum skill set to write C code. For me freshman CS101 for me, even biomedical students had to pass MSVC CS101 with VS IDE with a D grade, or the university will kick them out before christmas break. My SO in 2021 was required to pass 2 semesters of Python to graduate with her beauty/fashion degree. She single-stepped Python code infront of me on our 3rd date. She is a member of the general public, she is not a software dev. Hence, strace and a step debugger is minimum skill set to me.

What I would be very alarmed about is, lets take your p5p example,

C:\sources\perl5\win32>..\miniperl -I..\lib -Mstrict -e"print join(' ',%INC);"
..\lib/buildcustomize.pl ..\lib/buildcustomize.pl strict.pm C:\sources\perl5\lib
/strict.pm
C:\sources\perl5\win32>

See what happened? This is minimum skill set to be a Perl 5 coder. No P5P dark secrets or XS API or ISO C needed.

It would be a very different situation, if someone with a P5P commit bit, pushed a change to

splice(\@INC, 0, 1, $inc);

to obfuscate the existence of the lib/buildcustomize.pl disk file. Example.

C:\sources\perl5\win32>..\miniperl -I..\lib -Mstrict -e"delete $INC{'..\lib/buil
dcustomize.pl'}; print join(' ',%INC);"
strict.pm C:\sources\perl5\lib/strict.pm
C:\sources\perl5\win32>

I've never seen that any CPAN code like that. I would label seeing a statement like delete $INC{'..\lib/buil dcustomize.pl'}; as very suspicious. Its blackhat code without a very long src code comment justifying why its there. FOSS or paid, software libraries are forbidden from attempt to prevent a sysadmin/prof dev, from discovering their existence at runtime.

A 1 line src comment isn't good enough, half a page of rational or we have a problem. P5P perl's only attempt at syscall hooks at

/* In theory, passing a non-socket handle to closesocket() is fine. It

is perfectly okay with me. Counting every single link from that commit, to anything else on WWW or in any bug tracker, Perl's only case of syscall hook has 23 screen-fuls of backstory from my count. I didn't count -V copy pastes, just only comments/paragraphs excluding copy paste log data.

off topic for this bug, click to expand, Ruby vs Perl Vs Win32 vs Python is offtopicor 😈 "Actually we are rejecting this ticket because Python doesnt have a C API. Python is written in Python. Quoting C code from the CPython repo is 100% UB and contributes nothing to your claims."

P5/Ruby have a problem, that hard breaking all CPAN/Gem written in C modules at once, if they executing on Win32, is the worst bug fix choice if there is any choice at all to fix the most annoying !@$* win32-only race condition make test hang of all time.

I think 2023 fix win32 kernel syscall hooking done in 8552f09 it the best way to fix it once and for all. My attempt in 2013 in b47a847 I wrote it specifically to be not controversial and specifically NOT use "assembly code" even though I knew intercepting CloseHandle() in assembly is more bug-proof proof than a "pure C" fix. The pure C fix isn't the way the way I wouldve have done it for my own private/job related Perl/XS code. I knew my 2013 fix was fragile, it depended on MS never investing in its CRT/Libc again and never changing a certain reverse engineered C struct again. By 2017 1f664ef my 2013 fix was broke.

Assembly code and kernel syscall hooking in 8552f09 is much better, C function call CloseHandle() is MS public API contract, that C symbol will never be removed for the rest of Win32/Win64's platform's lifetime.

POSIX/Linux/OSX/BSD don't even have a concept of "public C API".

Linux's public API/ABI contract ends at byte sequence is 0x4C 0x8B 0xD1 0xB8 0x0C 0x00 0x00 0x00 0x0F 0x05 0xC3 on Intel 64/AMD CPUs. C has nothing to do with the Linux Kernel, looking at our repo is an implementation detail, did you even read the man page https://man7.org/linux/man-pages/man2/syscall.2.html with our API? This is not the bug tracker for GLIBC or GCC.

For MS/C/Win32/perl land, business choices un-deprecated the dangerous and memory unsafe ISO C/C++ langs around 2015 and MS decided following the latest ISO C/C++ specs instead of saying the dogma that C/C++ langs only for exist to support EOL legacy code bases, there is no such thing as new/greenfield C++ code, no professional dev will ever do that. Everyone understood MS retired/froze its C compiler at C89 and half froze its C++ compiler , in 2012 https://devblogs.microsoft.com/cppblog/c11-features-in-visual-c-11/ alot of features were missing (red) vs GCC. it was just that way. VC 2019/2022 things changed, and MSVC now tries to compete with Clang/LLVM/GCC instead of it being a grandfathered product.

The P5P interp has never ever used inline assembly code for any OS AFAIK until 2023 commit 8552f09 . 8552f09 is the first code in the interp ever that acknowledges what Intel X86/machine code/assembly language is. Perl interp really did spend 37 years assuming an Intel Xeon executes 3.5 billion printable ascii printable chars per second of C source code. In 2023 Perl learned matured into an adult and learned Santa Clause is not real, and CPUs don't know what ISO or K&R C code is.

Now that the perl interpreter is aware of assembly language, a good goal is Perl learning about SMP and that a PC can have more than 1 CPU core on a motherboard. Perl 5.6-5.41 ithreads and 5.41.X blead right now assume OS threads never simultaneous execute, any-OS/pthreads are just random longjmp() function calls done by pthreads, 2 threads can't execute at the same micro since OS threads are green threads, aren't they? (nope)

https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/stdatomic.h.html this exists in 2025. its not 2015 or 2005.

Blead perl 5.41 has 129 !!! call sites of EnterCriticalSection()/MUTEX_LOCK(m). my archived Blead perl 5.23 has 53 EnterCriticalSection()/MUTEX_LOCK(m). things changed. OS threads/hardware changed.

AFAIK PARISC/HPUX is the only SMP capable arch perl 5 ever ran on without ANY hardware assembly level atomic CPU ops. I tried looking for them. They just don't exist on PARISC. HP's official line was a syscall from user mode to the HPUX kernel (ring 0) is the 1 and only way to safely stop data corruption, PARISC CPUs are physically incapable of atomic anything, turning off interrupts is the only way to do safe threading, and thats always a privileged kernel op.

but bulk88 did research once exception in HPUX/PARISC, there is a voodoo secret spell for PARISC/HPUX. HP's engineerings found a "hardware errata" in the PARISC cpu with PARSIC's L1 cache flush opcode, where abusing/misusing that opcode, to smash/shard/data corrupt an unaligned U32 integer, the memory corruption hardware bug turned out to be atomic, certified atomic, we will license you the C code and an 5 year indemnity/liability contract certifiying that hardware bug is atomic for human life safety for the right price.

My free time reading stopped, when I found out, that atomic hardware bug, was ONLY an atomic broken sign bit on a if(U32 u32_1==U32 u32_2) {} on a C lang level, its sounds useless to me and perl, and most devs, because its a single bit, that you have to decker algo/spin lock into compare_add_swap() on every other Unix OS/CPU/Windows/OSX. I dont have a PHD and my day job is not inside a lithography silicon foundry. I'm closing the tab regarding HPUX/PARISC, its too low level for me and Perl and the perl community. I'm not an employee of HP given a work task to make HPUX win benchmarks/critical reviews against vanilla Linux users.

I sorta intended "XS handshake key" error to help out perl/unix C hackers who were using API hooking with Linux ShLibLoader's LD_PRELOAD feature, and getting the cause of a SEGV in your STDOUT shaved 30 seconds of your time vs getting the cause of a SEGV in gdb is great, but its not a "fix", everyone already is very experienced with C/gdb/low level programming, if they approach C API hooking. Anyone who knows what LD_PRELOAD is knows what they are doing and how to fix it themselves. saving 20 seconds in gdb is handy, its not life altering.

@bulk88
Copy link
Contributor Author

bulk88 commented Jan 25, 2025

That is an awful lot of info that I find hard to grasp, but I am triggered by
Config::Perl::V in combination with unsafe

Is Config::Perl::V unsafe? Does it need to be changed and if so how and
why (in short easy wording) or is this a CORE issue?

I just found a bug that changed my opinion about perl -V being "mockable" from debug/troubleshooting nightmare to a CVE level problem.

Collection of issues related to new procedure for disabling 'taint', including 5.36 blockers. #19657

Revert "Add Configure question for taint support" #19679

So how did Configure/Makefile.SH (C env state) get de-synchronised from Config.pm (PP env state) on Unix, and the most senior people in P5P got affected by stable perl/p5p git repo perl, outputting a false PP Config.pm file created by Configure/Makefile.SH?

quoting #19657

Execute: ./perl -Ilib -MConfig -le'print $Config{taint_support}' you will see it print out 'define', this is wrong. You can also do ./perl -Ilib -V:taint_support, you will see:

taint_support='define';

Grep ./perl -Ilib -V case-insensitively and you will not see anything about 'taint_support' but you will see NO_TAINT_SUPPORT or it and SILENT_NO_TAINT_SUPPORT depending on which you configured with:

./perl -Ilib -V | grep -i taint_support
    config_args='-Dusethreads -Doptimize=-g -d -Dusedevel -Dcc=ccache gcc -Dld=gcc -DDEBUGGING -Accflags=-DSILENT_NO_TAINT_SUPPORT'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -DSILENT_NO_TAINT_SUPPORT -fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DSILENT_NO_TAINT_SUPPORT -fwrapv -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    NO_TAINT_SUPPORT
    SILENT_NO_TAINT_SUPPORT

Expected behavior

  1. Assuming we keep 'taint_support' as a setting (see point 6 below) I expect that $Config{taint_support} to be false when perl was configured with either -Accflags='-DNO_TAINT_SUPPORT' or -Accflags='-DSILENT_NO_TAINT_SUPPORT'
  2. I do not expect perl to lie to me about a setting that does not exist being defined.

Same.

  1. I expect perl -V to show an important property like '$Config{taint_support}', yes it is visible in the list of defines under its true names, but that is not what users who use -Utaint_support will expect to be looking for.

Same.

  1. I expect to be able to distinguish SILENT_NO_TAINT_SUPPORT from NO_TAINT_SUPPORT in %Config. The only way to determine if a perl is compiled with NO_TAINT_SUPPORT when it is not already running under -T is to execute a perl script with -T and see if it dies with a message about not supporting taint.

I have some partial code to make -V/V.pm much more XSish, but there are alot of road blocks, like PL_bincompat_options/PL_non_bincompat_options isn't accurate,

non_bincompat_options is a lie
#13904](#13904 (comment))

a recount is showing 9 macros in 5.41 that are mislabeled/ABI up from 3 in the old ticket. So editing S__Internals_V() is fuzzy, or should S__Internals_V() be edited, or a new func, get getting very api design-ish.

I doubt its a good idea for S__Internals_V() to serve PP high level downstream consumers, and the no-PP perl.bin -V stderr C code at the same time, xsub API C prototype isnt set up for other C funcs to call it (call_sv() and direct func ptr calling work).

@guest20
Copy link

guest20 commented Jan 25, 2025

I'm sure I just lack imagination, but an example would help.

Oh, yeah. Yep, I see it now. Bug reports (and interrogation) being incorrect about taint support is pretty bad.

@richardleach
Copy link
Contributor

I just found a bug that changed my opinion about perl -V being "mockable" from debug/troubleshooting nightmare to a CVE level problem.

I'm sure this could vary depending upon user environment & threat model, but my thoughts are:

  • Unless there's a compelling reason otherwise, if "user with write permissions on a file writes to the file" is a security problem, then the problem is with the permissions on the file and the fix is to revoke the user's write permissions (or use an immutable filesystem).
  • If that's infeasible, a mitigation might be to use some kind of ephemeral instance.
  • If we burn the config into libperl, then there's still "user with write permissions on libperl goes and hex edits the config within", to say nothing about messing about with the likes of LD_PRELOAD.
  • I can't see defending against root users being within perl's threat model.

Skimming #19657, it's not immediately obvious to me that having a baked-in config would have prevent this.

More generally, shady version information (inadvertent or otherwise) is another good reason to ask users to include a minimum reproducible test case in bug reports.

I'm not saying there would be no benefits to baking in the configuration, just that I don't necessarily see it fixing some of the concerns raised in this threat.

(Also, I wonder whether there are any legitimate post-build modifications of Config.pm that happen out there? Such as part of an automated deployment, packaging, or some customisation process.)

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

No branches or pull requests

4 participants