Discussion:
read-only Config.pm, storing highly dynamic settings in perl core
bulk88
2015-07-31 05:24:42 UTC
Permalink
On Unix perl Config.pm is always root writable only. I presume that this
means that once a Perl is built, its Config.pm and Config_heavy.pl must
"work" forever. There is also the concept that perl binary can run on a
different machine/OS version than the one it was compiled on, especially
in Windows land, AKA binary packaging.

As part of getting Perl to run on Visual C 2015, there is a problem that
MS dropped an undocumented but mentioned in a C header MS API that
Perl uses to create a socket on Win32. For the rest of this post, to
greatly simplify things, since this is about purpose of Config.pm, not
Windows, I will say the undocumented MS API is a 128 bit GUID
representing a class name, an object of the class can not be created
without known the 128 bit GUID, or the C header define that gives the
128 bit GUID a pretty english name. This GUID is used in MS's libc. Each
version of Visual C has its own specific libc version and they are all
separate product lines. Perl's socket implementation must create an
object of this class to create and destroy a socket. Previously the GUID
was in a MS shipped C header and stable for 20-25 years, but now with VC
2015 the GUID was dropped from the C header, and it is now randomized by
the C++ compiler when this MS libc library is built by MS.

The undocumented class is still there, but its name is now an
unpredictable(*) GUID, but a skilled human can figure out the GUID once
they get their hands on the MS libc library binary. Worst case scenario,
the string is likely to change every time MS recompiles this C .dll/.so
and ships it in an OS update (security fix, service pack, or new release
of Windows). Perl/P5P maintainers can have a table of build numbers of
the DLL and the correct GUID to use, but such a table can only exist for
current known versions of the dll, not future unreleased versions.

If a user installs an update to the MS library from MS, and the GUID
changes, the next perl process on that machine either fatally errors the
first time a socket is created, or starts and fatally errors before
opening any perl source code file. Until the user installs the new GUID,
or reverts the security fix that updated the MS lib, his perl wont be
working.

Config.pm is created at perl build time. I've never seen any CPAN module
or public Perl code that edits the Config.pm of an installed perl. The
known GUIDs at perl release time can be shipped by P5P in C code, but
what about future GUIDs?

Should perl be storing the GUIDs to try in Config.pm? "perl -e"0""
currently loads no perl files. "perl -E"0"" loads feature.pm alone.
Maybe "perl -E"0"" depending on feature.pm being on disk is a bug.

There are 2 ways to do this, either the first time you call socket()
(Win32 perl already only loads the socket library the first time you
call socket() from PP), Win32 Perl will load Config.pm and get the GUIDs
at perl startup time unconditional. Perl will get always load Config.pm.
Or is it forbidden for perlfunc keywords from loading .pm files?

What if a windows user doesn't have write access to his Config.pm? Or
can it be assumed, if he was able to install a security fix that
replaced libc in C:/Windows/System32, he can write to Config.pm.

-E and Perl__core_swash_init (IIRC any use of a utf8 char winds up
calling Perl__core_swash_init) already load .pm files without any
require or use being written in PP code.

Should this GUID be the P5P shipped GUIDs in a .c file, plus a env var
(or Win32 registry setting) for user updating in the field, no Config.pm
ever involved?

Should the GUIDs be P5P shipped in a .c file, with the only updating
being in the next maint release? ("sucks to be you, uninstall the update
or wait a couple months for the next maint release. No more P5P support
for your perl? Go complain to
http://search.cpan.org/dist/Devel-PatchPerl/ and compile your own damn
Strawberry windoze luser [autoconf and unix shell required]").

*it is predictable, but the perl binary would double or triple in size
to embed a 3rd party GPL-only library to programatically figure out the
GUID, so thats not happening
Reini Urban
2015-07-31 05:40:53 UTC
Permalink
*it is predictable, but the perl binary would double or triple in size to embed a 3rd party GPL-only library to programatically figure out the GUID, so thats not happening
Cannot you query this GUID "version number” from it’s “name" at run-time cheaper, with a simplier C call? I forgot about the Win32 API in the meantime, but there must be 2 liner to get it, I hope. It should also be in the registry under the name. This would be 5 lines then.
It’s only needed for socket init.

Regarding Config: In converted it to XS in the meantime, because it was a major memory and performance hog, so I cannot even manipulate it anymore. You still could theoretically, but you shouldn’t.
bulk88
2015-07-31 08:50:26 UTC
Permalink
Post by Reini Urban
Post by bulk88
*it is predictable, but the perl binary would double or triple in
size to embed a 3rd party GPL-only library to programatically figure out
the GUID, so thats not happening
Cannot you query this GUID "version number” from it’s “name" at
run-time cheaper, with a simplier C call?
It is not a GUID in real life. It is a variable length binary string in
real life, either in "\x01\x01a\x03b\x04" format or
"44f1949fdc0f1db55eb32045ad36bf84134d2bf18b3cd78b8dfffd29cf9c5564b75c1bf327"
or number between 0 and 0xFFFFFFFF or 0xFFFFFFFFFFFFFFFF or a perl lang
regexp, I haven't decided that yet.

-------------------------------------------------------------------
For the rest of this post, to greatly simplify things, since this is
about purpose of Config.pm, not Windows, I will say the undocumented MS
API is a 128 bit GUID representing a class name, an object of the class
can not be created without known the 128 bit GUID, or the C header
define that gives the 128 bit GUID a pretty english name.
-------------------------------------------------------------------

The "GUID" being a setting is fictitious. You really dont want to know
what it is in real life. It will be more fun when I write the patch and
send it to the ML.
Post by Reini Urban
I forgot about the Win32 API in the meantime, but there must be 2
liner to get it, I hope. It should also be in the registry under the
name. This would be 5 lines then.
It’s only needed for socket init.
It isnt in the registry. It isn't a GUID/COM class in real life.
Post by Reini Urban
Regarding Config: In converted it to XS in the meantime, because it
was a major memory and performance hog, so I cannot even manipulate it
anymore. You still could theoretically, but you shouldn’t.
Is Config still a tied hash or not in your implementation? Is there a
file of "local" overrides? What if I put a Config.pm in /site/lib?
Reini Urban
2015-08-12 09:39:01 UTC
Permalink
Post by Reini Urban
Regarding Config: In converted it to XS in the meantime, because it
was a major memory and performance hog, so I cannot even manipulate it
anymore. You still could theoretically, but you shouldn’t.
Is Config still a tied hash or not in your implementation? Is there a file of "local" overrides? What if I put a Config.pm in /site/lib?
It is a tied hash using XS accessors, and forbidding writes, as before.
A local override is used for the miniperl stage using the traditional Config_heavy.pl,
but I’ll get rid of miniperl soon so this will go.

At run-time you need to use a local override like that, based on the temp. Config.pm (called Config_mini.pl) and Config_heavy.pl during build.

I don’t want to make Config writable at all, and perl5 never supported that officially.
It doesn’t save that much memory as warnings as XS and unicode as XS, but still.
The warnings perfect hash is extendable at run-time though, via warnings::register.

Reini Urban
***@cpan.org

Loading...