Search code examples
bashperlauthenticationsu

Why am I getting a permission denied when su'ing to a user?


If I su user from my home directory I am getting a permission denied for bash-completion, but if I su user from another directory there is no error.

Can't locate strict.pm:   lib/strict.pm: Permission denied at 
/usr/bin/vendor_perl/bash-complete line 7.
BEGIN failed--compilation aborted at /usr/bin/vendor_perl/bash-complete line 7.

Line 7 of the referenced file is use strict; ... included with every version of perl since at least the late 90s.

su user sources /etc/bash.bashrc and the user being su'd to .bashrc. Why would the calling user's location in the filesystem change this?

See my repo for more details, but I think I've gotten the necessary basics here.

Edit: More description of the setup.

I've added the following lines to /etc/bash.bashrc (which is where the error is happening):

if [[ $USER == 'testloginfiles' ]]; then
    echo "/etc/bash.bashrc (-: $-) ($(shopt login_shell))"
    printf '@INC: %s\n' $(perl -e 'print join ":", @INC')
fi

And this is the output if I am in my home directory:

$ pwd;su testloginfiles
/home/harleypig
Password: 
/etc/bash.bashrc (-: himBH) (login_shell        off)
@INC: lib:/usr/lib/perl5/5.28/site_perl:/usr/share/perl5/site_perl:/usr/lib/perl5/5.28/vendor_perl:/usr/share/perl5/vendor_perl:/usr/lib/perl5/5.28/core_perl:/usr/share/perl5/core_perl
Can't locate strict.pm:   lib/strict.pm: Permission denied at /usr/bin/vendor_perl/bash-complete line 7.
BEGIN failed--compilation aborted at /usr/bin/vendor_perl/bash-complete line 7.
/home/testloginfiles/.bashrc (-: himBH) (login_shell        off)
[testloginfiles@sweetums harleypig]$

If I am in another directory (e.g., /tmp) I get the following:

$ pwd ; su testloginfiles
/tmp
Password: 
/etc/bash.bashrc (-: himBH) (login_shell        off)
@INC: lib:/usr/lib/perl5/5.28/site_perl:/usr/share/perl5/site_perl:/usr/lib/perl5/5.28/vendor_perl:/usr/share/perl5/vendor_perl:/usr/lib/perl5/5.28/core_perl:/usr/share/perl5/core_perl
/home/testloginfiles/.bashrc (-: himBH) (login_shell            off)
[testloginfiles@sweetums tmp]$

There is a relative path as @pcronin suggests, but neither my home directory nor /tmp have a lib directory. Why is one causing an error and the other is not?


Solution

    1. In Perl, use strict tells perl to go find, load and import symbols from a file named strict.pm. It does this by searching the ordered list of directories in the @INC list. See this answer for more information on how that gets built. The error you are seeing indicates that before successfully finding a strict.pm, perl searched in a path that the executing user (likely testloginfiles) did not have access to.

    2. The contents of @INC can be affected by both the directory from which the script is run, as well as environment variables. In your case, since the problem manifests itself when the program is run from one directory but not another, it's likely that one (or more) of the entries in @INC is a relative path, such as lib (instead of something like /usr/share/perl5), or, that an environment variable that can affect perl's @INC list is different in the target user's environment.

    3. Running perl -E 'print join("\n", @INC)'; will produce a list of locations that it will search. Run that in your regular user's shell, and compare the results to what happens if you add it to testloginfiles' .bashrc file. The difference in output should explain the difference in behavior.

    UPDATE

    1. With the new information you provided, we see there are no differences in @INC, which leaves us to understand how the two cases interpreted @INC differently. As you found in the su man page, su isn't changing the current directory, which means that relative paths won't affect the intepretation of @INC at all. But, su is changing the user, so it means that the su'd user is testing if /home/harleypig/lib/strict.pm exists. I'd bet that the su'd user does not have permissions to read into harleypig's home directory to see if that file exists, thus causing the error.