Skip to content

WIP Add resolving of $PROGRAM_NAME from /dev/fd/number #23358

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 1 commit into
base: blead
Choose a base branch
from

Conversation

michal-josef-spacek
Copy link

There are situations when $PROGRAM_NAME is something /dev/fd/number

  1. example like sudo /usr/local/bin/<tool> with checksum verification - Issue with $PROGRAM_NAME (sudo + checksum verification) #23351
    → Resolves to the tool path
  2. example with pipe: perl <( echo '#!perl -DA'; echo 'print "$0\n"');
    → Stay with /dev/fd/number
  • This set of changes requires a perldelta entry, and I need help writing it.

@jkeenan jkeenan changed the title Add resoving of $PROGRAM_NAME from /dev/fd/number Add resolving of $PROGRAM_NAME from /dev/fd/number Jun 5, 2025
@michal-josef-spacek michal-josef-spacek force-pushed the fix_program_name_in_sudo branch 2 times, most recently from 085c026 to 99313c1 Compare June 5, 2025 15:24
Copy link
Contributor

@jkeenan jkeenan left a comment

Choose a reason for hiding this comment

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

These changes need to be exercised by our test suite. Such a test will have to take into account the quirks of different operating systems.

@jkeenan jkeenan added defer-next-dev This PR should not be merged yet, but await the next development cycle type-core labels Jun 5, 2025
@michal-josef-spacek michal-josef-spacek force-pushed the fix_program_name_in_sudo branch from 99313c1 to 6241f02 Compare June 5, 2025 16:32
There are situations when $PROGRAM_NAME is something /dev/fd/<number>
1) example like sudo /usr/local/bin/<tool> with checksum verification
(GH#23351)
2) example with pipe: perl <( echo '#!perl -DA'; echo 'print "$0\n"');
@michal-josef-spacek
Copy link
Author

There were issues in the build on Windows, I updated PR.

@michal-josef-spacek
Copy link
Author

hm, issue on Windows perl.obj : error LNK2019: unresolved external symbol readlink referenced in function S_open_script

@Leont
Copy link
Contributor

Leont commented Jun 6, 2025

This code should probably be feature guarded.

That means Configure should check if "/proc/self/fd/%d" actually works on that platform.

@bulk88
Copy link
Contributor

bulk88 commented Jun 10, 2025

What does this C code do when it executes on on Plan9, OS/2, Windows, and VMS?

@michal-josef-spacek
Copy link
Author

What does this C code do when it executes on on Plan9, OS/2, Windows, and VMS?

The actual plan is to create some configuration option to detect /proc/self/fd/%d and add a define to the actual code. ok?

@michal-josef-spacek michal-josef-spacek changed the title Add resolving of $PROGRAM_NAME from /dev/fd/number WIP Add resolving of $PROGRAM_NAME from /dev/fd/number Jun 10, 2025
@bulk88
Copy link
Contributor

bulk88 commented Jun 10, 2025

hm, issue on Windows perl.obj : error LNK2019: unresolved external symbol readlink referenced in function S_open_script

He tried to call readlink() on Windows. @bulk88 pulls out Neuralizer

P.S. readlink() exists on WinOS, but this PR/this patch, has no business knowing how to correctly spell the identifier to invoke Win32 OS's readlink() function.

Update:
JK JK this PR/this patch on Win32, also has no business knowing how to correctly spell in 7-bit ASCII the /proc and /dev directories on Windows. </joke>

I would be strongly against any patch that knows hows to reach NT Kernel's root dir called / and strip off the public api C:/ prefix. That "magic spell" is undocumented API, and has zero src code compatibility with POSIX targeted src code. All of WinNT's secret / directories are written in CamelCase/PascalCase with no spelling abbreviations 😁. Also don't ask how to locate the absolute path to the Windows Registry, or mount the Windows Registry database somewhere under /. And don't ask how get any PID's real time CPU usage and RSS and VSZ mem usage from a certain folder in the Windows Regsitry.

@@ -4227,6 +4227,19 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
Safefree(PL_origfilename);
PL_origfilename = (char *)scriptname;
}
else {
char proc_fd_path[64];
snprintf(proc_fd_path, sizeof(proc_fd_path), "/proc/self/fd/%d", fdscript);
Copy link
Contributor

Choose a reason for hiding this comment

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

"/proc/self/fd/" is 14 +1 chars
"/proc/self/fd/%d" is 16+ 1 chars

"%d" max legal expansion is 21 chars according to google but plz verify it, or find perl.h's or handy.h's official macro for max base10 expansion

"%d" is signed, what does "/proc/self/fd/-13" means on Linux?

The c stack buffer should really be 16+21+1 == 38 or with sizeof(size_t) round up logic, (16+21+1)/8 == 4.75; 5*8 == 40 b/c why not?

The CC will round up C auto var char[38] to the next 4 or 8 alignment mark no matter what you do.

@@ -4227,6 +4227,19 @@ S_open_script(pTHX_ const char *scriptname, bool dosearch, bool *suidscript)
Safefree(PL_origfilename);
PL_origfilename = (char *)scriptname;
}
else {
Copy link
Contributor

Choose a reason for hiding this comment

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

this else { block starting here really should be split off into a separate static, not-inline function, see my other comment below why this is needed

snprintf(proc_fd_path, sizeof(proc_fd_path), "/proc/self/fd/%d", fdscript);
char target_path[MAXPATHLEN];
SSize_t len = readlink(proc_fd_path, target_path, sizeof(target_path) - 1);
if (len != -1) {
Copy link
Contributor

Choose a reason for hiding this comment

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

On Linux and FooNix OSes, MAXPATHLEN is constant 1024, 4096, or 2**16 == 65536.

Those 3 buffer lengths are an alligator [S_open_script] taking a bite into a sub/hero/hoagie [C stk].

Since this huge C stk buffer is not used on all control flow paths through S_open_script, but the CC/machine code, needs to stretch the C stack by 1024/4096/65536 bytes each time upon entry, and then use Intel's U32 offsets operands everywhere in the machine code of this function's body, and not Intel's more efficient U8/I8 offset operand encoding choice. It is smarter to put this new else{} branch into its own dedicated static no-line function, so the new else{} branch, and new else{} branch's 1024 or upto 65536 bytes long C stk buffer, don't at runtime, affect the existing control flow paths inside ``S_open_script` that don't know, don't care, and don't use, that 1024-65536 stack buffer.

I have no tech/coding problem with this huge size + very short life span C stack buffer. I don't want to see it become another bloated wasteful Newx()/Safefree()/SAVEFREEPV() statement pair in perl code. I'd would prefer that not all 100% of permutations of all PP calls to PP do/require/use, force that 1024-65K buffer to temporarily exist while sitting unused on the C stack.

On WinPerl because of a P5P bug, CPP macro MAXPATHLEN is 1024 instead of MS's MAX_PATH == 256 or P5P's Win32 cargo cult of writing char bug [ MAX_PATH+1 ];. WinNT Kernel's real path limit is forever frozen at I16_MAX "characters of an undefined encoding", aka, a 32K long array of WCHARs. which becomes 65536 bytes or U16_MAX for the byte length of a 32K long array of WCHARs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defer-next-dev This PR should not be merged yet, but await the next development cycle type-core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants