in reply to perldb.ini permission problem on Windows 11

I dug into the perldb source and found this:
sub is_safe_file { my $path = shift; stat($path) || return; # mysteriously vaporized my ( $dev, $ino, $mode, $nlink, $uid, $gid ) = stat(_); return 0 if $uid != 0 && $uid != $<; return 0 if $mode & 022; return 1; } ## end sub is_safe_file

Then I did some experimentation using a test script on the perldb.ini file and determined that (a) the $uid was zero, and (b) the file permission was 0100666.

After some research I discovered that the mode on Windows includes the file type, and that one is supposed to mask it with 07777 in order to get the permissions. The code in the perldb source is not doing that, otherwise the mode would be 0666.

What the test is looking for, though, is a file with 0644. I've tried everything I can in the Properties-Security tab to get that, and no joy. I also tried the tool that was suggested, though it wasn't any easier to understand than the Properties Security tab. Anyway, at this point I managed to get a file that is owned by my userid, and that has no permissions for anyone else -- not even System or Administrators.

Here's what ls -la tells me:

ls -la perldb.ini -rw-r--r-- 1 jgpuckering 197615 140 Sep 18 11:44 perldb.ini
That looks right, yet when I do a stat on the file I still get 010066:
perl -MFile::stat -E "printf '%%07o', stat('perldb.ini')->mode" 0100666
One thing that is clear is that the perldb test is flawed on Windows. At the very least, it should be masking the mode with 07777 to get rid of the file type.

But beyond that, I think there's something fundamentally wrong with this test. Due to the inherent differences between Windows file security and Unix file security, there seems to be no way -- or at least, no obvious or easy way -- for a user to set the file permissions in Windows so that the file will pass the test.

I suspect that testing file access in this fashion on Windows using stat() simply doesn't work. The test should either be written differently for Windows, or disabled for Windows.

Perhaps this has been fixed in a later release. As I mentioned, I'm running v5.31.1 of Strawberry perl, which is the latest release I can get. I've got a workaround, but this seems to me to be a bug that has broken perldb.ini support on Windows.

Should I report this as a perl bug? If so, how and where?

Replies are listed 'Best First'.
Re^2: perldb.ini permission problem on Windows 11
by syphilis (Archbishop) on Sep 20, 2022 at 01:41 UTC
    sub is_safe_file { my $path = shift; stat($path) || return; # mysteriously vaporized my ( $dev, $ino, $mode, $nlink, $uid, $gid ) = stat(_); return 0 if $uid != 0 && $uid != $<; return 0 if $mode & 022; return 1; } ## end sub is_safe_file


    On Windows 7, I'm seeing the same result as the OP.
    The is_safe_file() sub returns 0, because $mode & 022 returns a true value of 18.
    But the leading 0100 is ignored, and the true value of 18 is obtained simply because the 2nd and 5th bits of $mode are true.

    This sub has been (in its current form) in perl5db.pl since perl-5.8.8 (maybe even earlier), and its behaviour has remained the same throughout that period.
    I know buggerall about perl5db.pl and file permissions, but it feels to me that this sub should not even be called on a Windows system.

    I did however find a file named simply "config_data" in a perl (not Strawberry Perl) bin folder of mine for which is_safe_file() returned true.
    For that file, the value of $mode, as seen by is_safe_file(), was 33206 (0100444).
    If you can set the perldb.ini permissions to that value then you might get lucky ;-)

    PUCKERING, if you want to raise an issue about this with the perl developers, then create a "New Issue" at https://github.com/Perl/perl5/issues.

    Cheers,
    Rob
      Thanks Rob.

      Your comments jogged my memory. I used to use ActiveState perl. The reason I was fiddling with perldb.ini is that my .perldb file wasn't working. After some experimentation, I realized it wasn't even being read. When I renamed it to perldb.ini it began being read, but with this error message we've been discussing.

      But at some point in the past it did work and without that message. That's why it was in my home directory. And so it was probably back when I was using ActiveState perl. My guess is they may have fixed this problem in their code, but that fix never made it into Strawberry perl.

      If I find the time I might test that hypothesis by having a peek at the ActiveState perl5db.pl code. And I will definitely post an issue per your suggestion.

Re^2: perldb.ini permission problem on Windows 11
by afoken (Chancellor) on Sep 21, 2022 at 17:51 UTC

    It seems Perl (or the C runtime) emulates stat() on Windows. The emulation roughly looks like what a common Unix system returns when an ACL system runs on top of the standard Unix permissions. See also Re^3: Inline.pm and untainting.

    sub is_safe_file { my $path = shift; stat($path) || return; # mysteriously vaporized my ( $dev, $ino, $mode, $nlink, $uid, $gid ) = stat(_); return 0 if $uid != 0 && $uid != $<; return 0 if $mode & 022; return 1; } ## end sub is_safe_file

    This piece of code has no idea of that emulation. Unfortunately, it also has no idea of an ACL system on top of Unix permissions. That should not hurt on Unix, because even with an ACL system on top of the Unix permissions, criticial files should have restrictive Unix permissions. The stat() emulation on Windows has no Unix permissions.

    So, is_safe_file() may need to disable the $mode check if $^O eq 'MSWin32'. Perhaps it should also add some Windows-specific ACL tests.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re^2: perldb.ini permission problem on Windows 11
by NERDVANA (Priest) on Sep 21, 2022 at 07:38 UTC
    At the very least, it should be masking the mode with 07777 to get rid of the file type.

    Well, technically it is. It is masking with octal 022, which is bit 1 and bit 4 (counting from zero) so no other bits are considered. Or in other words "is the world-write bit set?" or "is the group-write bit set?" and if either is set, then the result is true after the bitwise AND operator.

    It might be related to the "Everyone" user in Windows? Windows permissions inherit from parent, so I think you'd have to add a new permission for Everyone that explicitly sets "no permission". Disclaimer: I haven't used windows permissions in several years.